一个完全基本的问题--如果是重复的话,请原谅我。
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不是数组,而是具有非空值的类的对象(例如数据帧),那么如果X是二维(例如数据帧)或通过as.matrix (例如数据帧),则尝试通过as.array将其强制到数组。
发布于 2017-06-16 14:12:13
如果你必须使用你的功能,你可以做到,
sapply(split(df, 1:nrow(df)), f1)
# 1 2 3 4 5
#"b" "b" "c" "a" "c" 备注我将您的FUN重命名为f1,因为R中的各种函数都使用FUN来定义函数的参数
发布于 2017-06-16 14:20:19
另一种选择是对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"
#NULLhttps://stackoverflow.com/questions/44591238
复制相似问题