【问题标题】:select columns from dataframe where groups of samples are nonzero从样本组非零的数据框中选择列
【发布时间】:2016-10-04 15:26:04
【问题描述】:

我有一个按物种(列)数据框的样本(行)。另一个数据框中的一列将样本编码成组。我想选择所有组中的所有样本都具有非零值的所有列。

物种框架:

structure(list(Otu000132 = c(0L, 56L, 30L, 52L, 1L, 4L, 31L, 4L, 17L, 9L, 4L), 
               Otu000144 = c(191L, 14L, 58L, 137L, 127L, 222L, 26L, 175L, 133L, 107L, 43L),
               Otu000146 = c(0L, 0L, 0L, 0L, 16L, 62L, 41L, 16L, 60L, 32L, 0L), 
               Otu000147 = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), 
               Otu000151 = c(2L, 9L, 4L, 1L, 0L, 4L, 4L, 2L, 3L, 0L, 0L),
               Otu000162 = c(2L, 1L, 0L, 0L, 1L, 1L, 0L, 2L, 1L, 0L, 0L), 
               Otu000164 = c(2L, 0L, 1L, 2L, 0L, 0L, 0L, 0L, 0L, 0L, 0L),
               Otu000174 = c(0L, 0L, 3L, 1L, 0L, 2L, 0L, 1L, 2L, 1L, 0L), 
               Otu000176 = c(1L, 9L, 0L, 1L, 2L, 5L, 3L, 3L, 8L, 2L, 2L), 
               Otu000186 = c(1L, 0L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L),
               Otu000190 = c(1L, 1L, 1L, 0L, 0L, 5L, 1L, 2L, 7L, 0L, 0L)),
          .Names = c("Otu000132", "Otu000144", "Otu000146", "Otu000147", 
                     "Otu000151", "Otu000162", "Otu000164", "Otu000174", 
                     "Otu000176", "Otu000186", "Otu000190"),
          row.names = 30:40, class = "data.frame")

分组框架:

structure(c(30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
            40, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3), 
          .Dim = c(11L, 2L))

想要的输出:

structure(list(Otu000132 = c(0L, 56L, 30L, 52L, 1L, 4L, 31L, 4L, 17L, 9L, 4L), 
               Otu000144 = c(191L, 14L, 58L, 137L, 127L, 222L, 26L, 175L, 133L, 107L, 43L), 
               Otu000151 = c(2L, 9L, 4L, 1L, 0L, 4L, 4L, 2L, 3L, 0L, 0L), 
               Otu000176 = c(1L, 9L, 0L, 1L, 2L, 5L, 3L, 3L, 8L, 2L, 2L),
               Otu000190 = c(1L, 1L, 1L, 0L, 0L, 5L, 1L, 2L, 7L, 0L, 0L)), 
          .Names = c("Otu000132", "Otu000144",  "Otu000151", 
                     "Otu000176", "Otu000190"),
          row.names = 30:40, class = "data.frame")

我觉得这应该是我可以用 dplyr select 做的事情,但我想不通。任何人有建议让我走上一条道路?

【问题讨论】:

  • 不是很清楚。您将第三列作为“Otu000146”,其中有 4 个 0,即 30、31 和 32 为 0。该列是否应该包含在所需的输出中?否则sp1[!Reduce(&,lapply(split(gp1[,1], gp1[,2]), function(x) {x1 <- sp1[match(x, row.names(sp1)),]; colSums(x1==0)>0}))] 将提供所需的所有其他列。
  • 我的错误,我认为它存在于所有第 2 组中,但事实并非如此
  • 你能编辑你的帖子来改变预期的输出吗

标签: r dplyr data-management


【解决方案1】:

这确实可以通过 dplyr 以相当直接的方式完成。正如其他人指出的那样,“Otu000146”不符合您描述的标准,不会包含在最终的列选择中。

library(dplyr)
library(tidyr)

df.species <- cbind(species, group = grouping[,2]) %>% # merge the grouping variable into the main data set
    gather(variable, value, -group) %>%  # gather the columns into 'long' format
    group_by(variable, group) %>% # group by column name and group
    summarize(keep = all(value != 0)) %>% # variables and groups where all values are non-zero
    ungroup %>% group_by(variable) %>%  # reset grouping
    summarize(keep = any(keep)) %>%  # variables where at least 1 group met the aforementioned criterion
    dplyr::filter(keep) # final list

   variable  keep
      <chr> <lgl>
1 Otu000132  TRUE
2 Otu000144  TRUE
3 Otu000151  TRUE
4 Otu000176  TRUE
5 Otu000190  TRUE

# retrieve only the matching columns
df.desired <- species[df.species$variable]

   Otu000132 Otu000144 Otu000151 Otu000176 Otu000190
30         0       191         2         1         1
31        56        14         9         9         1
32        30        58         4         0         1
33        52       137         1         1         0
34         1       127         0         2         0
35         4       222         4         5         5
36        31        26         4         3         1
37         4       175         2         3         2
38        17       133         3         8         7
39         9       107         0         2         0
40         4        43         0         2         0

【讨论】:

  • gather 不在 dplyr,也需要加载 tidyr
【解决方案2】:

我们将split 的第一列分组数据集 ('gp1') 通过第二列 (gp1[,2]) 到 list,循环通过 list,通过匹配其行来子集物种数据集的行带有list元素的名称,获取逻辑矩阵(x1==0)的列和,检查是否大于0,使用&amp;中的&amp;比较每个list元素的对应元素@,否定( !) 将 TRUE 更改为 FALSE(反之亦然)的索引以子集物种数据集的列。

sp1[!Reduce(`&`,lapply(split(gp1[,1], gp1[,2]), function(x) {
                x1 <- sp1[match(x, row.names(sp1)),]
                colSums(x1==0)>0}))]
#    Otu000132 Otu000144 Otu000151 Otu000176 Otu000190
#30         0       191         2         1         1
#31        56        14         9         9         1
#32        30        58         4         0         1
#33        52       137         1         1         0
#34         1       127         0         2         0
#35         4       222         4         5         5
#36        31        26         4         3         1
#37         4       175         2         3         2
#38        17       133         3         8         7
#39         9       107         0         2         0
#40         4        43         0         2         0

【讨论】:

  • 这行得通,谢谢。我选择了另一个,因为很难理解 lapply 中发生的事情
【解决方案3】:

您可以使用 dplyr 或仅使用基本功能:

species = merge(species, group, by.x=c("row.names"), by.y=c("V1"))

#Find the lowest values in each grouping
check = aggregate(species[,c("Otu000132", "Otu000144", "Otu000146", 
                   "Otu000147", "Otu000151", "Otu000162", "Otu000164", 
                   "Otu000174", "Otu000176", "Otu000186", "Otu000190")], 
                    by=list(species$V2), min)

#sum across the groupings
vars = apply(check, 2, function(x) sum(x))

#retain variables where sum > 1, indicating at least one grouping has full observations
vars = vars[vars!=0]

#extract the variable names
vars = names(vars)[-1]

#subset dataset to select variables identified above
out = species[vars]

out
#   Otu000132 Otu000144 Otu000151 Otu000176 Otu000190
#1          0       191         2         1         1
#2         56        14         9         9         1
#3         30        58         4         0         1
#4         52       137         1         1         0
#5          1       127         0         2         0
#6          4       222         4         5         5
#7         31        26         4         3         1
#8          4       175         2         3         2
#9         17       133         3         8         7
#10         9       107         0         2         0
#11         4        43         0         2         0

【讨论】:

  • 你有一些/所有的困惑。这对每列的每个组求和,或者换句话说,组中的任何值是否非零。 OP 想了解所有值均非零的组,然后获取具有符合该条件的任何组的列。
  • 你是对的,感谢您的关注。我修改了代码来解决这个问题。
猜你喜欢
  • 2018-09-21
  • 2020-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多