R 如何将每列中的字符转换为子列而不重复

R 如何将每列中的字符转换为子列而不重复,r,reshape,tidyr,R,Reshape,Tidyr,我有一个data.frame文件,如下所示: 输入: 我想将每列中的ecah字符转换为一个子列,并且我想将1或0放入行中,以表示是否在该特定行中观察到该子列: 输出数据帧: 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

我有一个data.frame文件,如下所示: 输入:

我想将每列中的ecah字符转换为一个子列,并且我想将1或0放入行中,以表示是否在该特定行中观察到该子列: 输出数据帧:

   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中有什么解决方案可以做到这一点吗?同时,我的真实数据有117000行和10000列。

我们可以使用
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

要输出,请使用
write.csv(newdat,file=“yourfilename.csv”)

我们可以使用
base R中的
表格
来完成。我们
unlist
数据集,
paste
使用以
c
开头的新列名,使用
is.NA
删除
NA
元素,获得带有行序列和
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

nm1如果
310
876
也在同一行中重复,该怎么办?是否会为每次重复创建一个新列以保持数据帧的二进制性?@Richard Scriven:如果存在NA,则必须在输出中将其设置为零。@Pierre Lafortune:这无关紧要。正如您在第7行中看到的,444在out put文件中重复了2次。他在问,如果一行是
310 444
?然后根据您的输出,您需要第二个
310
列。对于
876
也一样。然后,如果这三个都是
444
?您需要三列
444
吗?到目前为止,这有点令人困惑@Richard Scriven:是的,这是真的。如果一行是310 444,那么您需要第二行是310。如果是444,那么444需要3列。这仍然令人困惑吗?@jeremycg:我试图运行你的脚本,但我遇到了以下错误:>库中的库(dplyr)错误(dplyr):没有名为'dplyr'>library(tidyr)的包库中的错误(tidyr):没有名为'tidyr'的包。你能指导我如何安装这些库吗?
install.packages(“dplyr”)
然后
安装.packages(“tidyr”)
。您只需执行一次。@jeremycg:如何将此新数据文件提取为data.frame格式?我的意思是,如果我想将此输出作为new.txt文件,那么我应该向脚本中添加什么?查看编辑-基本上将输出保存为
newdat
,然后使用
write.csv
@akrun将其写入csv:我的输入是一个名为dat的txt数据帧,我想知道我应该在脚本的哪个部分替换我的dat.frame名称?我应该如何将输出提取为data.frame?@zara将
df1
替换为
dat
。它现在应该可以工作了。@zara也可以用
as.data.frame.matrix(
@akrun,谢谢。但是如何像new.txt文件一样将输出提取为data.frame呢?@zara你可以像jeremycg的回答一样使用
write.csv
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))
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