我想在R中的数据帧的每一行上应用一些函数。
该函数可以返回单行数据帧或没有(我猜'return()'什么都不返回?)。
我想在给定数据帧的每一行上应用此函数,并获得结果数据帧(可能更短,即行数少于原始行)。
例如,如果原始数据框类似于:
id size name
1 100 dave
2 200 sarah
3 50 ben
我正在使用的函数在数据帧中获取一行(即单行数据帧),如果名称与“brave”押韵,则返回原样,否则返回null,则结果应为:< / p>
id size name
1 100 dave
这个例子实际上是指对数据帧进行过滤,我希望得到一个特定于这种任务的答案,但也希望得到一个更一般的情况,即使是辅助函数的结果(在单个操作上的那个)行)可以是具有单行的任意数据帧。请注意,即使在过滤的情况下,我也想使用一些复杂的逻辑(不是像$size>100
这样的简单逻辑,而是一个由函数检查的更复杂的条件,让我们说boo(single_row_df)
。 / p>
P.S。
到目前为止我在这些情况下所做的是使用apply(df, MARGIN=1)
然后使用do.call(rbind ...)
,但我认为当我的数据帧只有一行(我得到Error in do.call(rbind, filterd) : second argument must be a list
)时,它给我带来了一些麻烦。 p>
更新
在斯蒂芬回答后,我做了以下事情:
ranges.filter <- function(ranges,boo) {
subset(x=ranges,subset=!any(boo[start:end]))
}
然后我使用一些看起来像这样的范围数据框来调用ranges.filter
:
start end
100 200
250 400
698 1520
1988 2147
...
和一些布尔矢量
(TRUE,FALSE,TRUE,TRUE,TRUE,...)
我想过滤掉布尔向量中包含TRUE值的任何范围。例如,如果位置100 .. 200
中的布尔向量为FALSE
,则第一个范围100 .. 200
将保留在数据框中。
这似乎可以完成这项工作,但我收到警告numerical expression has 53 elements: only the first used
。
答案 0 :(得分:4)
对于处理数据帧的更一般情况,例如从CRAN获取plyr包并查看ddply函数。
install.packages(plyr)
library(plyr)
help(ddply)
你想要什么,没有大量的摆弄。
例如......
> d
x y z xx
1 1 0.68434946 0.643786918 8
2 2 0.64429292 0.231382912 5
3 3 0.15106083 0.307459540 3
4 4 0.65725669 0.553340712 5
5 5 0.02981373 0.736611949 4
6 6 0.83895251 0.845043443 4
7 7 0.22788855 0.606439470 4
8 8 0.88663285 0.048965094 9
9 9 0.44768780 0.009275935 9
10 10 0.23954606 0.356021488 4
我们想要计算由“xx”定义的组中x的平均值和sd:
> ddply(d,"xx",function(r){data.frame(mean=mean(r$x),sd=sd(r$x))})
xx mean sd
1 3 3.0 NA
2 4 7.0 2.1602469
3 5 3.0 1.4142136
4 8 1.0 NA
5 9 8.5 0.7071068
它优雅地处理了有时会让你感到困惑的所有令人讨厌的边缘情况。
答案 1 :(得分:1)
您可能必须使用lapply
代替apply
来强制将结果作为列表。
> rhymesWithBrave <- function(x) substring(x,nchar(x)-2) =="ave"
> do.call(rbind,lapply(1:nrow(dfr),function(i,dfr)
+ if(rhymesWithBrave(dfr[i,"name"])) dfr[i,] else NULL,
+ dfr))
id size name
1 1 100 dave
但在这种情况下,subset
会更合适:
> subset(dfr,rhymesWithBrave(name))
id size name
1 1 100 dave
如果要在返回结果之前执行其他转换,可以返回上面的lapply
方法:
> add100tosize <- function(x) within(x,size <- size+100)
> do.call(rbind,lapply(1:nrow(dfr),function(i,dfr)
+ if(rhymesWithBrave(dfr[i,"name"])) add100tosize(dfr[i,])
+ else NULL,dfr))
id size name
1 1 200 dave
或者,在这个简单的情况下,将函数应用于subset
的输出。
> add100tosize(subset(dfr,rhymesWithBrave(name)))
id size name
1 1 200 dave
<强>更新强>
要选择不在开始和结束之间的行,您可以构造一个不同的函数(注意:当对布尔/逻辑向量的求和求和时,TRUE值转换为1并且FALSE值转换为0)
test <- function(x)
rowSums(mapply(function(start,end,x) x >= start & x <= end,
start=c(100,250,698,1988),
end=c(200,400,1520,2147))) == 0
subset(dfr,test(size))
答案 2 :(得分:0)
听起来你想使用subset
:
subset(orig.df,grepl("ave",name))
第二个参数求值为一个逻辑表达式,用于确定保留哪些行。您可以使此表达式使用任意数量的列,例如grepl("ave",name) & size>50