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

在R中创建新的数据帧重组列,r,data-manipulation,R,Data Manipulation,我看过类似的帖子,但没有得到任何解决我的问题 我有一个数据帧(df),具有两个特征的不同大小(S042:4个大小,S081:3个大小)作为5个个体的变量(样本): 我想创建一个新的数据框架,将每个特征的数据重组为两列(因为每个特征都有一个或两个大小,没有更多)。如果单个有一个大小,则第二列必须有一个“0”。如果单列没有大小(NA),则两列都必须有“NA”。另外,将特征列名重命名为_1和_2,保留特征名称 新的dataframe最终将看起来像: Sample S042_1 S042_2 S08

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

我有一个数据帧(df),具有两个特征的不同大小(S042:4个大小,S081:3个大小)作为5个个体的变量(样本):

我想创建一个新的数据框架,将每个特征的数据重组为两列(因为每个特征都有一个或两个大小,没有更多)。如果单个有一个大小,则第二列必须有一个“0”。如果单列没有大小(NA),则两列都必须有“NA”。另外,将特征列名重命名为_1和_2,保留特征名称

新的dataframe最终将看起来像:

  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
来完成,方法是从
\uu
中删除字符。然后,使用
lappy
grep
此模式循环此操作,以获得具有相同前缀的列。对于后跟0的每一行,可以使用“应用”获取非
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

S4要清楚:每个部分(SO42部分、SO81部分)要么是:所有NAs;正好一个非零值;正好是两个非零值。其他可能性(三个非零值,NA加一个值)是不可能的?你是对的。特征的列数是可变的,取决于不同大小的列数。列可以包括非零值和零(至少一个非零值)。不允许使用NA加号值。谢谢Dash2。它可以工作,但我需要一个代码来应用于大量的特性,以便重新组织成不同数量的列。在我的示例中,每个特征的最大列数是2,但我还需要根据样本类型在3、4或5列中重新组织。@Akrun执行的代码解决了我的问题。非常好!!谢谢。我可以改变尺寸的“大小”重组在2,3,4。。。柱。另外,我创建了一个对象来收集df的唯一列名并重命名dfN的列名。我错过了这篇文章。我在这里有些东西要学。我需要更多的训练才能写出你的第一个想法+1和往常一样。@jazzurro谢谢,如果你经常使用
lappy/sapply,这会变得更容易。我对
lappy
apply
很满意。我对
sapply
很满意。但我仍然落后于
tapply
mapply
,例如。教程中的一些简单示例几乎没有帮助。因此,每当我在So中看到这些,我都会做笔记。同样,我仍在观察
Reduce
Map
在SO中的使用情况。任何关于
Reduce
Map
?@jazzurro
Reduce
的建议都类似于
do.call
。你可以在列表中使用它。例如,如果您想从列表中获取向量的对应元素之和(例如),
Reduce(
+
,lst)
假设没有
NAs
。当存在多个长度/维度相等的向量/列表/数据帧时,我们可以执行
Map/mapply
,您需要对相应的元素执行一些操作。
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
 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))