当我使用apply将一行数据帧传递给一个函数时,我丢失了该行元素的类信息.他们都变成了"性格".以下是一个简单的例子.我想给3个年龄段的人增加几年的时间.当我尝试添加2一个数字值时,R表示"对二元运算符的非数字参数".我该如何避免这种情况?
age = c(20, 30, 50)
who = c("Larry", "Curly", "Mo")
df = data.frame(who, age)
colnames(df) <- c( '_who_', '_age_')
dfunc <- function (er) {
print(er['_age_'])
print(er[2])
print(is.numeric(er[2]))
print(class(er[2]))
return (er[2] + 2)
}
a <- apply(df,1, dfunc)
Run Code Online (Sandbox Code Playgroud)
输出如下:
_age_
"20"
_age_
"20"
[1] FALSE
[1] "character"
Error in er[2] + 2 : non-numeric argument to binary operator
Run Code Online (Sandbox Code Playgroud)
apply只适用于矩阵(所有元素的类型相同).当你在a上运行它时data.frame,它只是as.matrix先调用.
最简单的方法是仅处理数字列:
# skips the first column
a <- apply(df[, -1, drop=FALSE],1, dfunc)
# Or in two steps:
m <- as.matrix(df[, -1, drop=FALSE])
a <- apply(m,1, dfunc)
Run Code Online (Sandbox Code Playgroud)
的drop=FALSE需要,避免受到单个列向量.
-1例如,意味着只有第一列,您可以明确指定所需的列df[, c('foo', 'bar')]
UPDATE
如果希望函数一次访问一个完整的data.frame行,则至少有两个选项:
# "loop" over the index and extract a row at a time
sapply(seq_len(nrow(df)), function(i) dfunc(df[i,]))
# Use split to produce a list where each element is a row
sapply(split(df, seq_len(nrow(df))), dfunc)
Run Code Online (Sandbox Code Playgroud)
对于大型数据帧,第一个选项可能更好,因为它不必预先创建庞大的列表结构.