r - 计算行意味着无需提供列名称并根据每列总和有选择地删除列

标签 r function dplyr

给出以下数据集:

library(tidyverse)
# example data
df1 = data.frame(ID = c("daisy", "lily", "rose", "tulip", "poppy", "iris", "orchid", "lotus", "crocus"), 
                 loc1 = c(10, 20, 30, 40, 50, 60, 70, 80, 90),
                 loc2 = c(100, 200, 300, 400, 500, 600, 700, 800, 900), 
                 loc3 = c(0, 0, 0, 0, 0, 0, 0, 0, 0), 
                 loc4 = c(1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000))

问题 1:对于每一行,提取最小值,计算平均值,并将两个结果附加到数据集。适用于以下代码:

df1 %>%  
  rowwise() %>% 
  mutate(Min = min(c(loc1, loc2, loc3, loc4)), Mean = mean(c(loc1, loc2, loc3, loc4)))

如何使代码更通用,以便它可以应用于数据集中的所有列,例如不包含因子或字符串?当我有 100 多个列时,我希望避免输入列名称。我尝试了以下方法:

df1 %>%  
  rowwise() %>% 
  mutate(Min =  min(is_double(df1)), Mean = mean(is_double(df1)))

但它没有产生期望的结果:

ID      loc1  loc2  loc3  loc4 Median  Mean
  <fct>  <dbl> <dbl> <dbl> <dbl> <lgl>  <dbl>
1 daisy     10   100     0  1000 FALSE      0
2 lily      20   200     0  2000 FALSE      0
3 rose      30   300     0  3000 FALSE      0

如何解决这个问题?

问题 2:如何计算每列中值的总和,然后删除 sum = 0 的列,同时将删除的列的名称保存在向量或数据框中(这样我就可以将名称保存到文件中)?

我试过了

cs <- colSums(df1[,2:ncol(df1)])
df1 %>% 
  select(which(cs > 0))

但是得到一个非常奇怪的结果,其中列名称发生了移位,并且仅包含“0”的列被保留。

loc1 loc2 loc4
1  daisy   10    0
2   lily   20    0
3   rose   30    0
4  tulip   40    0

有什么建议吗?

非常感谢!

最佳答案

使用select_if我们可以选择数字列

library(dplyr)
library(matrixStats)
df1 %>%
    mutate(Median = select_if(., is.numeric) %>% 
                               as.matrix %>% 
                              rowMedians, 
           Mean =select_if(., is.numeric) %>% 
                        rowMeans )

或者转换为“长”格式,然后按进行分组

library(dplyr)
library(tidyr)
df1 %>% 
   select_if(is.numeric) %>%
   mutate(rn = row_number()) %>%
   pivot_longer(cols = -rn) %>%
   group_by(rn) %>%
   summarise(Median = median(value), Mean = mean(value), Min = min(value)) %>%
   select(-rn) %>% 
   bind_cols(df1, .)
#      ID loc1 loc2 loc3 loc4 Median   Mean Min
#1  daisy   10  100    0 1000     55  277.5   0
#2   lily   20  200    0 2000    110  555.0   0
#3   rose   30  300    0 3000    165  832.5   0
#4  tulip   40  400    0 4000    220 1110.0   0
#5  poppy   50  500    0 5000    275 1387.5   0
#6   iris   60  600    0 6000    330 1665.0   0
#7 orchid   70  700    0 7000    385 1942.5   0
#8  lotus   80  800    0 8000    440 2220.0   0
#9 crocus   90  900    0 9000    495 2497.5   0

获取数字列的总和,并且仅当列总和大于0时才进行sum条件

df1 %>% 
     summarise_if(~is.numeric(.) && sum(.) > 0, sum)
#  loc1 loc2  loc4
#1  450 4500 45000

或者使用基础R

Filter(sum, colSums(df1[-1]))
#  loc1  loc2  loc4 
#   450  4500 45000 

如果目的是选择具有sum > 0和numeric的列,则使用select_if

df1 %>% 
   select_if(~ is.numeric(.) && sum(.) > 0)
#  loc1 loc2 loc4
#1   10  100 1000
#2   20  200 2000
#3   30  300 3000
#4   40  400 4000
#5   50  500 5000
#6   60  600 6000
#7   70  700 7000
#8   80  800 8000
#9   90  900 9000

或者也包含第一列因子

df1 %>% 
    select_if(~ is.factor(.)|(is.numeric(.) && sum(.) > 0))
#      ID loc1 loc2 loc4
#1  daisy   10  100 1000
#2   lily   20  200 2000
#3   rose   30  300 3000
#4  tulip   40  400 4000
#5  poppy   50  500 5000
#6   iris   60  600 6000
#7 orchid   70  700 7000
#8  lotus   80  800 8000
#9 crocus   90  900 9000

或者使用OP的代码,我们向其中添加+ 1,因为cs是通过删除第一列创建的

df1 %>% 
      select(which(cs > 0)+1)

包括第一列

df1 %>% 
     select(1, which(cs > 0)+1)

或者从“df1”中删除第一列,然后使用OP帖子中的代码

df1 %>%
  select(-1) %>%
  select( which(cs > 0))

关于r - 计算行意味着无需提供列名称并根据每列总和有选择地删除列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59461189/

相关文章:

c - 如何将二维数组发送到函数?

r - 计算平均发动机预期生命周期之间的比率

r - 如何用 R 提取一天中的分钟数?

r - 扩大数据框并插入缺失的列

r - 如果 R 中另一列中的值是连续的,则追加列的值

javascript - 更改 js 函数的定义在某些浏览器中不起作用

function - 我在 BlobStorage 触发器上遇到启动错误

r - 指定应用 read_csv 的列数

在 R 中使用 dplyr reshape 表格

r - 使用 ggdendro 在树状图的片段下显示变量标签