在R中重新组织列,创建新的数据帧



我看过类似的帖子,但没有得到任何东西来解决我的问题。

我有一个数据帧(df),它有两个不同大小的特征(S042:4大小,S081:3大小)作为5个人的变量(示例):

  Sample S042_91 S042_93 S042_105 S042_107 S081_184 S081_187 S081_188
1   6001      91       0        0      107      184      187        0
2   6002       0      93      105        0        0        0      188
3   6005      91       0      105        0        0        0      188
4   6006       0       0        0      107        0      187      188
5   6008      91       0        0      107       NA       NA       NA

我想创建一个新的数据框架,根据限制为两列的特征重新组织数据(因为每个人都有一个或两个大小,不再有)。如果单个具有一个大小,则第二列必须具有"0"。如果单个没有大小(NA),则两列都必须有"NA"。此外,将特征列名重命名为_1和_2,保留特征名称。

新的数据帧最终看起来像:

  Sample S042_1 S042_2 S081_1 S081_2
1   6001     91    107    184    187
2   6002     93    105    188      0
3   6005     91    105    188      0
4   6006    107      0    187    188
5   6008     91    107     NA     NA

提前非常感谢。

创建一个包含唯一列名的向量,这些列名具有不同的前缀,第一列除外。这可以使用gsub通过剥离从_开始的字符来完成。然后,使用lapplygrep循环此模式,以获得具有相同前缀的列。对于后面跟0的每一行,可以使用apply获取不是0的元素。

size <- 1:2
nm1 <-  paste0("^", unique(gsub("\_.*", "", colnames(df)[-1])))
dfN <- cbind(df[,1],do.call(data.frame,
         lapply(nm1, function(x) t(apply(df[grep(x, colnames(df))],1,
                function(x) c(x[x!=0], x[x==0])[size])))))
 colnames(dfN) <- c("Sample", paste(rep(c('SO42', 'SO81'), each=2), 1:2, sep="_"))

 dfN
 #  Sample SO42_1 SO42_2 SO81_1 SO81_2
 #1   6001     91    107   184    187
 #2   6002     93    105   188     0
 #3   6005     91    105   188     0
 #4   6006    107      0   187    188
 #5   6008     91    107    NA    NA

dplyr/tidyr 的另一种使用方法

 library(dplyr)
 library(tidyr)
 df %>% 
    gather(Var, Val, -Sample) %>%
    separate(Var, c("Var1", "Var2")) %>%
    group_by(Sample, Var1) %>% 
    arrange(Val==0) %>%
    slice(1:2) %>%
    mutate(n=row_number()) %>%
    ungroup() %>%
    unite(Var, Var1, n) %>% 
    select(-Var2) %>% 
    spread(Var, Val)
 #    Sample S042_1 S042_2 S081_1 S081_2
 #1   6001     91    107    184    187
 #2   6002     93    105    188      0
 #3   6005     91    105    188      0
 #4   6006    107      0    187    188
 #5   6008     91    107     NA     NA
S4 <- apply(tmp, 1, function (x) sort(x[2:5], decreasing=TRUE)[1:2])
S8 <- apply(tmp, 1, function (x) sort(x[6:8], decreasing=TRUE)[1:2])
newdata <- cbind(t(S4), t(S8))

未经测试但应该有效。重命名列并使其成为数据帧由您完成。

最新更新