我看过类似的帖子,但没有得到任何东西来解决我的问题。
我有一个数据帧(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
通过剥离从_
开始的字符来完成。然后,使用lapply
和grep
循环此模式,以获得具有相同前缀的列。对于后面跟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))
未经测试但应该有效。重命名列并使其成为数据帧由您完成。