我有一个包含多列的数据框 . 对于数据框中的每一行,我想在该行上调用一个函数,并且该函数的输入使用该行中的多个列 . 例如,假设我有这个数据,这个testFunc接受两个args:
> df <- data.frame(x=c(1,2), y=c(3,4), z=c(5,6))
> df
x y z
1 1 3 5
2 2 4 6
> testFunc <- function(a, b) a + b
假设我想将此testFunc应用于列x和z . 因此,对于第1行,我想要1 5,而对于第2行,我想要2 6.有没有办法在不编写for循环的情况下执行此操作,可能使用apply函数系列?
我试过这个:
> df[,c('x','z')]
x z
1 1 5
2 2 6
> lapply(df[,c('x','z')], testFunc)
Error in a + b : 'b' is missing
但得到错误,任何想法?
EDIT: 我想要调用的实际函数不是简单的总和,而是power.t.test . 我使用b只是为了举例 . 最终目标是能够做这样的事情(用伪代码编写):
df = data.frame(
delta=c(delta_values),
power=c(power_values),
sig.level=c(sig.level_values)
)
lapply(df, power.t.test(delta_from_each_row_of_df,
power_from_each_row_of_df,
sig.level_from_each_row_of_df
))
其中结果是每行df的power.t.test的输出向量 .
10 回答
您可以将
apply
应用于原始数据的子集 .或者如果你的函数只是sum使用矢量化版本:
如果你想使用
testFunc
EDIT 要按名称访问列而不是索引,您可以执行以下操作:
data.frame
是list
,所以......对于 vectorized functions
do.call
通常是一个不错的选择 . 但论证的名称开始发挥作用 . 这里使用args x和y来调用testFunc
来代替a和b ....
允许传递不相关的args而不会导致错误:对于 non-vectorized functions ,
mapply
将起作用,但您需要匹配args的顺序或明确命名它们:有时
apply
会起作用 - 因为当所有args属于同一类型时,将data.frame
强制转换为矩阵不会因更改数据类型而导致问题 . 你的例子是这种 .如果要在其中传递参数的另一个函数中调用函数,则有一个比这些更明智的方法 . 如果你想走这条路,研究
lm()
身体的第一行 .使用
mapply
使用dplyr包的新答案
如果要应用的函数是矢量化的,则可以使用
dplyr
包中的mutate
函数:与plyr包的旧答案
在我的拙见中,最适合该任务的工具是
plyr
来自plyr
包 .例:
不幸的是,正如Bertjan Broeksema指出的那样,如果你不在
mdply
调用中使用数据帧的所有列,这种方法就会失败 . 例如,许多函数已经是向量化,因此不需要任何迭代(
for
循环或*pply
函数) . 你的testFunc
就是这样一个例子 . 你可以简单地打电话:一般来说,我建议首先尝试这种矢量化方法,看看它们是否能得到你想要的结果 .
或者,如果您需要将多个参数传递给未向量化的函数,
mapply
可能就是您要查找的内容:其他人已正确指出
mapply
是为此目的而制作的,但(为了完整起见)概念上更简单的方法就是使用for
循环 .这是另一种方法 . 它更直观 .
我觉得有些答案没有考虑的一个关键方面,我指出后代,是apply()让你轻松进行行计算,但只适用于矩阵(所有数字)数据
对于数据帧,仍然可以对列进行操作:
要对行进行操作,我们首先进行转置 .
缺点是我相信R会复制你的数据表 . 这可能是一个记忆问题 . (这真的很难过,因为在程序上简单的tdf只是原始df的迭代器,因此节省了内存,但R不允许指针或迭代器引用 . )
另外,一个相关的问题是如何对数据帧中的每个单独的单元进行操作 .
我来这里寻找tidyverse功能名称 - 我知道它存在 . 为(我的)未来参考和
tidyverse
爱好者添加此项:purrrlyr:invoke_rows
(旧版本中为purrr:invoke_rows
) .通过连接到原始问题中的标准统计方法,broom包可能会有所帮助 .
@ user20877984的答案很棒 . 由于他们总结得比我之前的答案好得多,所以这是我(可能仍然是粗制滥造)尝试应用这个概念:
以基本方式使用
do.call
:处理完整的数据集:
lapply
power.t.test
函数指向每行的指定值:如果data.frame列是不同的类型,
apply()
有问题 . 关于行迭代的一个微妙之处是当列是不同的类型时apply(a.data.frame, 1, ...)
如何对字符类型进行隐式类型转换;例如 . 因子和数字列 . 这是一个使用因子的例子一列修改数字列:减法失败,因为列被转换为字符类型 .
一种解决方法是将第二列反向转换为数字:
但是可以通过将列保持分离并使用
mapply()
来避免转换:mapply()
是必需的,因为[[ ]]
不接受矢量参数 . 因此,通过将一个向量传递给[]
,通过更丑陋的代码,可以在减法之前完成列迭代: