【问题标题】:Apply FUN row-wise on data frame with integer and character variables在具有整数和字符变量的数据帧上逐行应用 FUN
【发布时间】:2017-06-16 14:02:33
【问题描述】:

一个完全基本的问题 - 如果它是重复的,请原谅我。

set.seed(1)
df <- 
  data.frame(id=c('a', 'a', 'b', 'b', 'a'),
             a=sample(1:10, size=5, replace=T),
             b=sample(1:10, size=5, replace=T),
             c=sample(1:10, size=5, replace=T)) 

那么,

> df
  id  a  b c
1  a  3  9 3
2  a  4 10 2
3  b  6  7 7
4  b 10  7 4
5  a  3  1 8

要返回具有最大值的列名(a、b 或 c),如果这是在 id 变量中取第二高,我使用下面的函数。

FUN <- function(r) {
  top <- names(r[,c('a', 'b', 'c')])[order(r[,c('a', 'b', 'c')], decreasing=T)]
  ifelse(top[1] == r[['id']], top[2], top[1])
}

我能做到:

FUN(df[1,]) #[1] "b"

对于所有行:

res <- NULL
for(i in 1:nrow(df)) {
res <- c(res, FUN(df[i,]))  
}

得到

> res
[1] "b" "b" "c" "a" "c"

但是我怎么能apply这个呢?例如。这不起作用:

apply(df, 1, FUN)

我怀疑问题在于 FUN 假定一个 1 行数据框(而不是一个命名的字符向量,如(第一行))

 id   a   b   c 
"a" "3" "9" "c"

来自apply?

如果 X 不是数组,而是具有非 null 暗值的类的对象(例如数据框),则应用尝试通过 as.matrix 将其强制转换为二维数组(例如, 一个数据框) 或通过 as.array.

【问题讨论】:

  • 你必须使用那个功能吗?或者您是否正在寻找获取最大列数的方法?
  • 我试图了解,一般来说,如何使用期望数据帧行的函数按行执行操作。

标签: r function dataframe row apply


【解决方案1】:

如果你必须使用你的函数,你可以这样做,

sapply(split(df, 1:nrow(df)), f1)
#  1   2   3   4   5 
#"b" "b" "c" "a" "c" 

注意我将你的FUN重命名为f1,因为FUN被R中的各种函数用来定义函数的参数

【讨论】:

  • 啊,正是!您可以使用split 逐行获取列表,然后将其输入lapply。很棒,也很一般。
  • 我在这里使用sapply 来获取向量,但如果您希望结果出现在列表中,您也可以使用lapply
  • 确定sapply是我想要的(如lapply(x, f1, simplify=F, USE.NAMES=F)
【解决方案2】:

另一种选择是对您的FUN 进行一些小的修改。我认为您遇到的问题是apply 会将每一行视为一个向量。由于您的 id 列是一个字符,这意味着您的 a/b/c 列也将被强制转换为字符。意识到这一点,我们可以稍微修改FUN 将其转换回numeric 以进行排序:

FUN <- function(r) {
  top <- c('a', 'b', 'c')[order(as.numeric(r[c('a', 'b', 'c')]), decreasing=T)]
  ifelse(top[1] == as.character(r['id']), top[2], top[1])
}

apply(df, 1, FUN)
#[1] "b" "b" "c" "a" "c"

要更详细地了解它是如何工作的,您可以运行以下命令并看到 apply 正在读取命名字符向量。

apply(df, 1, function(x) {print(x); print(class(x)); return(NULL)})
#  id    a    b    c 
# "a" " 3" " 9"  "3" 
#[1] "character"
#  id    a    b    c 
# "a" " 4" "10"  "2" 
#[1] "character"
#  id    a    b    c 
# "b" " 6" " 7"  "7" 
#[1] "character"
#  id    a    b    c 
# "b" "10" " 7"  "4" 
#[1] "character"
#  id    a    b    c 
# "a" " 3" " 1"  "8" 
#[1] "character"
#NULL

【讨论】:

  • 是的,我怀疑但想避免as.numericas.character
  • 我包含了as.character,因为我不知道r["id"] 是否是一个因素。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-14
  • 2012-08-16
  • 2014-10-01
  • 1970-01-01
相关资源
最近更新 更多