在 R 函数中调用 data.frame 列?
Call data.frame columns inside of R functions?
正确的做法是什么?
我有一个函数,在给定一系列输入的情况下,它自己可以很好地工作,我想在大型数据集上使用这个函数,而不是通过逐行循环数据来处理奇异值。我尝试更新函数以调用 data.frame 列而不是向量值,但没有成功。
一个简单的例子是:
假设我有一个包含 4 列的 date.frame,data$id、data$height、data$weight、data$gender。我想编写一个函数来遍历每一行(使用应用)并计算 BMI (kg/m^2)。我知道使用 dplyr 很容易做到,但我想学习如何在不求助于外部包的情况下做到这一点,但找不到如何正确引用函数中的列的明确答案。
如有重复请提前致歉。我一直在非常彻底地搜索 Whosebug,希望找到一个现有的例子。
我想这就是您要找的。从功能上引用数据框列的最简单方法是使用带引号的列名。原则上,你做的是这个
data[, "weight"] / data[, "height"]^2
但在函数内部您可能希望让用户指定高度或体重列的名称不同,因此您可以编写函数
add_bmi = function(data, height_col = "height", weight_col = "weight") {
data$bmi = data[, weight_col] / data[, height_col]
return(data)
}
此函数将假设要使用的列默认命名为 "height" 和 "weight",但用户可以根据需要指定其他名称。您可以改用列索引来执行类似的解决方案,但使用名称往往更容易调试。
这么简单的功能很少有用。如果您正在计算大量数据集的 BMI,也许值得保留此函数,但由于它是 base R 中的单行函数,您可能不需要它。
my_data$BMI = with(my_data, weight / height^2)
需要注意的是,使用存储在变量中的列名意味着您不能使用 $
。这是我们通过让事情变得更加程序化而付出的代价,对于这样的应用程序养成一个好习惯是一个好习惯。见 fortunes::fortune(343)
:
Sooner or later most R beginners are bitten by this all too convenient shortcut. As an R newbie, think of
R as your bank account: overuse of $-extraction can lead to undesirable consequences. It's best to
acquire the '[[' and '[' habit early.
-- Peter Ehlers (about the use of $-extraction)
R-help (March 2013)
对于像 dplyr
这样的更高级的用法,你不需要引用列名等(并且可以计算表达式),lazyeval
包使事情相对轻松并且有非常好的小插曲.
基函数with
可以用来做一些懒惰的评估,例如
with(mtcars, plot(disp, mpg))
# sometimes with is nice
plot(mtcars$disp, mtcars$mpg)
但 with
最好以交互方式和简单的脚本使用。如果您开始编写程序化生产代码(例如,您自己的 R 包),避免非标准评估会更安全。例如,请参阅 ?subset
中的警告,这是另一个使用非标准评估的基本 R 函数。
一般来说,函数不应该知道比它们需要知道的更多的东西。如果您编写一个需要 data.frame 的函数,而在 data.frame 中提供输入数据并不是必需的,那么您会使您的函数比需要的更具限制性。
该函数的正确写法如下:
bmi <- function(height,weight) weight/height^2;
这将允许您根据身高值向量和体重值向量计算 BMI 值向量,因为 /
和 ^
都是向量化运算。所以,例如,如果你有两个松散的身高和体重向量,那么你可以这样称呼它:
set.seed(1);
N <- 5;
height <- rnorm(N,1.7,0.2);
weight <- rnorm(N,65,4);
BMI <- bmi(height,weight);
height; weight; BMI;
## [1] 1.574709 1.736729 1.532874 2.019056 1.765902
## [1] 61.71813 66.94972 67.95330 67.30313 63.77845
## [1] 24.88926 22.19652 28.91995 16.50967 20.45224
如果您的输入包含在 data.frame 中,您将能够这样做:
set.seed(2);
N <- 5;
df <- data.frame(id=1:N, height=rnorm(N,1.7,0.2), weight=rnorm(N,65,4), gender=sample(c('M','F'),N,replace=T) );
df$BMI <- bmi(df$height,df$weight);
df;
## id height weight gender BMI
## 1 1 1.520617 65.52968 F 28.33990
## 2 2 1.736970 67.83182 M 22.48272
## 3 3 2.017569 64.04121 F 15.73268
## 4 4 1.473925 72.93790 M 33.57396
## 5 5 1.683950 64.44485 M 22.72637
提供这个答案是因为我无法在 SO 上找到它并且我的头撞在墙上试图弄清楚为什么我的 R 包中的函数假设我的新列是一个对象而不是 data.frame列。
如果函数接受 data.frame 并且在函数中添加和转换附加列,方法如下:
example_func <- function(df) {
# To add a new column
df[["New.Column"]] <- value
# To get the ith value of that column
df[[i, "New.Column"]]
# To subset set the df using some conditional logic on that column
df[df[["New.Column"]]==value]
# To sort on that column
setorderv(df, "New.Column", -1)
}
注意这需要 library(devtools)
正确的做法是什么?
我有一个函数,在给定一系列输入的情况下,它自己可以很好地工作,我想在大型数据集上使用这个函数,而不是通过逐行循环数据来处理奇异值。我尝试更新函数以调用 data.frame 列而不是向量值,但没有成功。
一个简单的例子是:
假设我有一个包含 4 列的 date.frame,data$id、data$height、data$weight、data$gender。我想编写一个函数来遍历每一行(使用应用)并计算 BMI (kg/m^2)。我知道使用 dplyr 很容易做到,但我想学习如何在不求助于外部包的情况下做到这一点,但找不到如何正确引用函数中的列的明确答案。
如有重复请提前致歉。我一直在非常彻底地搜索 Whosebug,希望找到一个现有的例子。
我想这就是您要找的。从功能上引用数据框列的最简单方法是使用带引号的列名。原则上,你做的是这个
data[, "weight"] / data[, "height"]^2
但在函数内部您可能希望让用户指定高度或体重列的名称不同,因此您可以编写函数
add_bmi = function(data, height_col = "height", weight_col = "weight") {
data$bmi = data[, weight_col] / data[, height_col]
return(data)
}
此函数将假设要使用的列默认命名为 "height" 和 "weight",但用户可以根据需要指定其他名称。您可以改用列索引来执行类似的解决方案,但使用名称往往更容易调试。
这么简单的功能很少有用。如果您正在计算大量数据集的 BMI,也许值得保留此函数,但由于它是 base R 中的单行函数,您可能不需要它。
my_data$BMI = with(my_data, weight / height^2)
需要注意的是,使用存储在变量中的列名意味着您不能使用 $
。这是我们通过让事情变得更加程序化而付出的代价,对于这样的应用程序养成一个好习惯是一个好习惯。见 fortunes::fortune(343)
:
Sooner or later most R beginners are bitten by this all too convenient shortcut. As an R newbie, think of R as your bank account: overuse of $-extraction can lead to undesirable consequences. It's best to acquire the '[[' and '[' habit early.
-- Peter Ehlers (about the use of $-extraction) R-help (March 2013)
对于像 dplyr
这样的更高级的用法,你不需要引用列名等(并且可以计算表达式),lazyeval
包使事情相对轻松并且有非常好的小插曲.
基函数with
可以用来做一些懒惰的评估,例如
with(mtcars, plot(disp, mpg))
# sometimes with is nice
plot(mtcars$disp, mtcars$mpg)
但 with
最好以交互方式和简单的脚本使用。如果您开始编写程序化生产代码(例如,您自己的 R 包),避免非标准评估会更安全。例如,请参阅 ?subset
中的警告,这是另一个使用非标准评估的基本 R 函数。
一般来说,函数不应该知道比它们需要知道的更多的东西。如果您编写一个需要 data.frame 的函数,而在 data.frame 中提供输入数据并不是必需的,那么您会使您的函数比需要的更具限制性。
该函数的正确写法如下:
bmi <- function(height,weight) weight/height^2;
这将允许您根据身高值向量和体重值向量计算 BMI 值向量,因为 /
和 ^
都是向量化运算。所以,例如,如果你有两个松散的身高和体重向量,那么你可以这样称呼它:
set.seed(1);
N <- 5;
height <- rnorm(N,1.7,0.2);
weight <- rnorm(N,65,4);
BMI <- bmi(height,weight);
height; weight; BMI;
## [1] 1.574709 1.736729 1.532874 2.019056 1.765902
## [1] 61.71813 66.94972 67.95330 67.30313 63.77845
## [1] 24.88926 22.19652 28.91995 16.50967 20.45224
如果您的输入包含在 data.frame 中,您将能够这样做:
set.seed(2);
N <- 5;
df <- data.frame(id=1:N, height=rnorm(N,1.7,0.2), weight=rnorm(N,65,4), gender=sample(c('M','F'),N,replace=T) );
df$BMI <- bmi(df$height,df$weight);
df;
## id height weight gender BMI
## 1 1 1.520617 65.52968 F 28.33990
## 2 2 1.736970 67.83182 M 22.48272
## 3 3 2.017569 64.04121 F 15.73268
## 4 4 1.473925 72.93790 M 33.57396
## 5 5 1.683950 64.44485 M 22.72637
提供这个答案是因为我无法在 SO 上找到它并且我的头撞在墙上试图弄清楚为什么我的 R 包中的函数假设我的新列是一个对象而不是 data.frame列。
如果函数接受 data.frame 并且在函数中添加和转换附加列,方法如下:
example_func <- function(df) {
# To add a new column
df[["New.Column"]] <- value
# To get the ith value of that column
df[[i, "New.Column"]]
# To subset set the df using some conditional logic on that column
df[df[["New.Column"]]==value]
# To sort on that column
setorderv(df, "New.Column", -1)
}
注意这需要 library(devtools)