как скрыть символ в каждом столбце как подстолбец без дублирования

У меня есть такой файл data.frame: input:

1 200 444 444
2 310 NA  444
3 310 NA  444
4 NA  444 444
5 200 444 444
6 200 NA  444
7 310 444 444 
8 310 876 444
9 310 876 444
10 NA  876 444

Я хочу преобразовать символ ecah в каждом столбце в качестве подстолбца, и я хочу поместить 1 или ноль в строки так, как они представляют, наблюдался ли подстолбец в этой конкретной строке или нет: Выходные данные.кадр:

   c1.200 c1.310 c2.444 c2.876 c3.444
1   1      0      1      0      1 
2   0      1      0      0      1
3   0      1      0      0      1
4   0      0      1      0      1
5   1      0      1      0      1
6   1      0      0      0      1
7   0      1      1      0      1
8   0      1      0      1      1
9   0      1      0      1      1
10  0      0      0      1      1

есть ли решение в R для этого? Между тем, в моих реальных данных было 117 000 строк и 10 000 столбцов.


person zara    schedule 22.09.2015    source источник
comment
Что, если бы 310 или 876 также повторялись в той же строке? Будет ли создаваться новый столбец для каждого повтора, чтобы сохранить бинарный фрейм данных?   -  person Pierre L    schedule 23.09.2015
comment
@ Ричард Скривен: когда есть NA, то он должен быть установлен как ноль в выводе.   -  person zara    schedule 23.09.2015
comment
@ Пьер Лафортюн: это не имеет значения. как вы видите в строке 7, 444 повторяется 2 раза в выходном файле.   -  person zara    schedule 23.09.2015
comment
Он спрашивает, что если строка 310 310 444? Затем, согласно вашему выводу, вам понадобится второй столбец 310. И то же самое для 876. А что, если все трое 444? Вам нужны три столбца 444? Пока это немного сбивает с толку   -  person Rich Scriven    schedule 23.09.2015
comment
@ Ричард Скривен: да, это правда. если строка 310 310 444 , вам понадобится вторая строка для 310 . и если 444, вам нужно 3 столбца для 444. Это все еще сбивает с толку?   -  person zara    schedule 23.09.2015
comment
Разве это не имело бы больше смысла и было бы легче читать, если бы у вас было это как 200 310 444 444 876?   -  person Rich Scriven    schedule 23.09.2015
comment
@ Ричард Скривен: нет, потому что мои данные на самом деле представляют собой код генотипа вдоль участка хромосомы.   -  person zara    schedule 23.09.2015


Ответы (2)


Мы могли бы сделать это, используя table из base R. Мы unlist набор данных, paste с новыми именами столбцов, которые начинаются с c, удаляем элементы NA с помощью is.na, получаем table с последовательностью строк и вектором paste.

nm1 <- paste0('c', 1:3, '.')[col(dat)]
v1 <- unlist(dat)
i1 <- !is.na(v1)
newdat <- as.data.frame.matrix(table((1:nrow(dat))[row(dat)][i1], 
                         paste0(nm1[i1], v1[i1])))
newdat
#     c1.200 c1.310 c2.444 c2.876 c3.444
#  1       1      0      1      0      1
#  2       0      1      0      0      1
#  3       0      1      0      0      1
#  4       0      0      1      0      1
#  5       1      0      1      0      1
#  6       1      0      0      0      1
#  7       0      1      1      0      1
#  8       0      1      0      1      1
#  9       0      1      0      1      1
#  10      0      0      0      1      1
person akrun    schedule 23.09.2015
comment
@ akrun: мой ввод - это фрейм данных txt с именем dat, мне интересно, в какой части вашего скрипта я должен заменить свое имя dat.frame? и как мне извлечь вывод в виде data.frame? - person zara; 23.09.2015
comment
@zara Заменил df1 на dat. Теперь это должно работать. - person akrun; 23.09.2015
comment
@zara Также оберните as.data.frame.matrix( - person akrun; 23.09.2015
comment
@akrun спасибо. но как извлечь вывод в виде файла data.frame, такого как файл new.txt? - person zara; 23.09.2015
comment
@zara Вы можете использовать write.csv, как в ответе jeremycg. - person akrun; 23.09.2015

Мы можем сделать это, используя dplyr и tidyr:

library(dplyr)
library(tidyr)
newdat <- dat %>% setNames(paste0("c", 1:ncol(.), ".")) %>%
        mutate(row = row_number(), n = 1) %>%
        gather(key, val, -row, -n) %>%
        na.omit %>%
        unite(keyval, key, val, sep = "") %>%
        spread(keyval, n, fill = 0)

   row c1.200 c1.310 c2.444 c2.876 c3.444
1    1      1      0      1      0      1
2    2      0      1      0      0      1
3    3      0      1      0      0      1
4    4      0      0      1      0      1
5    5      1      0      1      0      1
6    6      1      0      0      0      1
7    7      0      1      1      0      1
8    8      0      1      0      1      1
9    9      0      1      0      1      1
10  10      0      0      0      1      1

Я использовал этот набор данных, как dat:

structure(list(V2 = c(200L, 310L, 310L, NA, 200L, 200L, 310L, 
310L, 310L, NA), V3 = c(444L, NA, NA, 444L, 444L, NA, 444L, 876L, 
876L, 876L), V4 = c(444L, 444L, 444L, 444L, 444L, 444L, 444L, 
444L, 444L, 444L)), .Names = c("V2", "V3", "V4"), class = "data.frame", row.names = c(NA, 
-10L))

Для вывода используйте write.csv(newdat, file="yourfilename.csv")

person jeremycg    schedule 23.09.2015
comment
@jeremycg: я попытался запустить ваш скрипт, но получил следующие ошибки: › библиотека (dplyr) Ошибка в библиотеке (dplyr): нет пакета с именем «dplyr» › библиотека (tidyr) Ошибка в библиотеке (tidyr): нет пакет под названием «tidyr», не могли бы вы подсказать, как установить эти библиотеки? - person zara; 23.09.2015
comment
install.packages("dplyr"), затем install.packages("tidyr"). Вам нужно будет сделать каждый только один раз. - person jeremycg; 23.09.2015
comment
@jeremycg: как я могу извлечь этот новый файл данных в формате data.frame? Я имею в виду, если я хочу, чтобы этот вывод был в виде файла new.txt, то что я должен добавить в сценарий? - person zara; 23.09.2015
comment
см. редактирование - в основном сохраните вывод как newdat, затем запишите его в csv, используя write.csv - person jeremycg; 23.09.2015