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

时间:2015-09-22 23:01:11

标签: r reshape tidyr

我有一个像这样的data.frame文件: 输入:

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或0放入行中: 输出data.frame:

   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行和10,000列。

2 个答案:

答案 0 :(得分:2)

我们可以使用dplyrtidyr执行此操作:

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")

答案 1 :(得分:1)

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