当我不知道 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))
还有来自purrrlyr
的by_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 函数时的主要内容,如果未能解决你的问题,请参考以下文章