当我不知道 data.frame 中的列名时,当我使用 dplyr mutate 函数时

Posted

技术标签:

【中文标题】当我不知道 data.frame 中的列名时,当我使用 dplyr mutate 函数时【英文标题】:When I don't know column names in data.frame, when I use dplyr mutate function 【发布时间】:2019-02-09 20:58:02 【问题描述】:

我想知道当我不知道列名时如何使用 dplyr mutate 函数。这是我的示例代码;

library(dplyr)
w<-c(2,3,4)
x<-c(1,2,7)
y<-c(1,5,4)
z<-c(3,2,6)
df <- data.frame(w,x,y,z)
df %>% rowwise() %>% mutate(minimum = min(x,y,z))

Source: local data frame [3 x 5]
Groups: <by row>

# A tibble: 3 x 5
      w     x     y     z     minimum
    <dbl> <dbl> <dbl> <dbl>   <dbl>
1     2     1     1     3       1 
2     3     2     5     2       2 
3     4     7     4     6       4

此代码按行查找最小值。是的,“df %>% rowwise() %>% mutate(minimum = min(x,y,z))”之所以有效,是因为我输入了列名 x、y、z。但是,让我们假设我有一个非常大的 data.frame 有几百列,而且我不知道所有的列名。或者,我有多个 data.frame 数据集,它们都有不同的列名;我只想在每行和每个 data.frame 中找到第 10 列到第 20 列的最小值。

在我上面提供的这个示例 data.frame 中,假设我不知道列名,但我只想获取每行中从第 2 列到第 4 列的最小值。当然,这是行不通的,因为 'mutate' 不适用于向量;

df %>% rowwise() %>% mutate(minimum=min(df[,2],df[,3], df[,4]))  

Source: local data frame [3 x 5]
Groups: <by row>

# A tibble: 3 x 5
       w     x     y     z    minimum
     <dbl> <dbl> <dbl> <dbl>   <dbl>
 1     2     1     1     3       1
 2     3     2     5     2       1
 3     4     7     4     6       1

下面这两个代码也不起作用。

 df %>% rowwise() %>% mutate(average=min(colnames(df)[2], colnames(df)[3], colnames(df)[4]))  
 df %>% rowwise() %>% mutate(average=min(noquote(colnames(df)[2]), noquote(colnames(df)[3]), noquote(colnames(df)[4])))  

我知道当我不知道列名时,我可以通过使用 apply 或不同的方法来获得最小值。但是,我想知道 dplyr mutate 函数是否能够在没有已知列名的情况下做到这一点。

谢谢,

【问题讨论】:

您可能需要某种 tidyeval 方法。喜欢mutate(minimum = min(!!!syms(names(df)[2:4])))。如果您决定使用 tidyeval,请查看一些 tidyeval 资源的汇总here。 谢谢奥史密斯!我要学习tidyeval。 【参考方案1】:

apply:

library(dplyr)
library(purrr)

df %>%
  mutate(minimum = apply(df[,2:4], 1, min))

pmap:

df %>%
  mutate(minimum = pmap(.[2:4], min))

还有来自purrrlyrby_row

df %>%
  purrrlyr::by_row(~min(.[2:4]), .collate = "rows", .to = "minimum")

输出:

# tibble [3 x 5]
      w     x     y     z minimum
  <dbl> <dbl> <dbl> <dbl>   <dbl>
1     2     1     1     3       1
2     3     2     5     2       2
3     4     7     4     6       4

【讨论】:

感谢您的帮助!这些例子非常简单明了。多亏了你,我学到了一些新东西。【参考方案2】:

矢量化选项为pmin。使用 syms 将列名转换为符号并计算 (!!!) 以返回应用 pmin 的列的值

library(dplyr)
df %>% 
  mutate(minimum = pmin(!!! rlang::syms(names(.)[2:4])))
#  w x y z minimum
#1 2 1 1 3       1
#2 3 2 5 2       2
#3 4 7 4 6       4

【讨论】:

谢谢阿克伦。这很有趣!我会更多地研究这个。【参考方案3】:

这里是一个tidyeval 方法,符合 aosmith 的建议。如果您不知道列名,您可以创建一个函数来接受所需位置作为输入并查找列名本身。在这里,rlang::syms() 将列名作为字符串并将它们转换为符号,!!! 将符号取消引用并将其拼接到函数中。

library(dplyr)
w<-c(2,3,4)
x<-c(1,2,7)
y<-c(1,5,4)
z<-c(3,2,6)
df <- data.frame(w,x,y,z)

rowwise_min <- function(df, min_cols)
  cols <- df[, min_cols] %>% colnames %>% rlang::syms()
  df %>%
    rowwise %>%
    mutate(minimum = min(!!!cols))


rowwise_min(df, 2:4)
#> Source: local data frame [3 x 5]
#> Groups: <by row>
#> 
#> # A tibble: 3 x 5
#>       w     x     y     z minimum
#>   <dbl> <dbl> <dbl> <dbl>   <dbl>
#> 1     2     1     1     3       1
#> 2     3     2     5     2       2
#> 3     4     7     4     6       4
rowwise_min(df, c(1, 3))
#> Source: local data frame [3 x 5]
#> Groups: <by row>
#> 
#> # A tibble: 3 x 5
#>       w     x     y     z minimum
#>   <dbl> <dbl> <dbl> <dbl>   <dbl>
#> 1     2     1     1     3       1
#> 2     3     2     5     2       3
#> 3     4     7     4     6       4

由reprex package (v0.2.0) 于 2018 年 9 月 4 日创建。

【讨论】:

感谢 Calum 的详细解释!!我对此进行了测试,它可以工作。

以上是关于当我不知道 data.frame 中的列名时,当我使用 dplyr mutate 函数时的主要内容,如果未能解决你的问题,请参考以下文章

没有NA的data.frame的最佳子集

将 R data.frame 强制转换为 nz.data.frame 时出错

在 lag() 中将字符串作为列名传递

在过滤R data.frames时更新因子水平[重复]

替换列名 gsub 中的字符

将 data.frame 列名传递给函数