我想将权重应用于R中的数据框,该数据框由数字和因子的变量组成。当我创建一个将因子转换为数字然后对变量进行加权并将其应用于任何给定列的函数时,它运行良好。但是,当我使用apply
函数将其应用于data.frame时,它会生成NA。例如:
set.seed(123)
frame <- data.frame(x = sample(1:100,10), y = c(rep("1",5), rep("2",5)))
weights <- 10
weight.fun <- function(x){
x <- if(class(x) == "numeric" | class(x) == "integer"){x} else {as.numeric(levels(x))[x]}
x*weights
}
weight.fun(frame$x)
# [1] 290 790 410 860 910 50 500 830 510 420
weight.fun(frame$y)
# [1] 10 10 10 10 10 20 20 20 20 20
apply(frame,2,weight.fun)
# x y
# [1,] NA NA
# [2,] NA NA
# [3,] NA NA
# [4,] NA NA
# [5,] NA NA
# [6,] NA NA
# [7,] NA NA
# [8,] NA NA
# [9,] NA NA
# [10,] NA NA
有关为何会发生这种情况的任何想法吗?
答案 0 :(得分:4)
如果您使用sapply
代替apply
,操作将按预期运行:
sapply(frame, weight.fun)
# x y
# [1,] 290 10
# [2,] 790 10
# [3,] 410 10
# [4,] 860 10
# [5,] 910 10
# [6,] 50 20
# [7,] 500 20
# [8,] 830 20
# [9,] 510 20
# [10,] 420 20
这种差异的原因是apply
对矩阵(或数组)进行操作。来自?apply
:
返回通过应用a获得的向量或数组或值列表 函数到数组或矩阵的边距。
因此,在使用frame
时,您的数据框apply
将转换为矩阵,这意味着所有列的数据类型将被强制相同(在您的情况下为字符串):
as.matrix(frame)
# x y
# [1,] "29" "1"
# [2,] "79" "1"
# [3,] "41" "1"
# [4,] "86" "1"
# [5,] "91" "1"
# [6,] " 5" "2"
# [7,] "50" "2"
# [8,] "83" "2"
# [9,] "51" "2"
# [10,] "42" "2"
这解释了apply
的意外行为 - weight.fun
正在传递字符向量。
同时,sapply
对列表进行操作,这正是您想要的,因为数据帧是列表。使用sapply
,每个列的类型都保留在数据框中,因此首先使用整数向量调用weight.fun
,然后使用因子调用它。
答案 1 :(得分:0)
看起来问题出在你的职能部门。你的if语句是返回NA的,所以这不是一个应用问题,如果x是一个字符,它将失败。编写这样的函数似乎适用于apply。
set.seed(123)
frame <- data.frame(x = sample(1:100,10), y = c(rep("1",5), rep("2",5)))
weight.fun <- function(x, w = 10){
if(!class(x) == "numeric" & !class(x) == "integer") {
if(class(x) == "factor") { x <- as.numeric(as.character(x)) }
else if(class(x) == "character") { x <- as.numeric(x) }
}
return(x * w)
}
apply(frame, MARGIN = 2, FUN = weight.fun)