[英]R-language: function to process data in data frame
场景是存在一个函数,该函数从数据框中的列获取值,进行一些处理,然后用结果填充另一列。
这是测试的简化版本:
#the function checks if the value in inVar1 exists.
#if it does then it returns the value, if not it returns -100
#inRow: for debugging
test2 <- function (inVar1,inRow)
{
#debug
print(paste("Row=",inRow, " inVar1=", inVar1, sep=''))
if(is.na(inVar1) || is.null(inVar1))
{
#debug
print("position 1")
ret <- -100
}
else
{
#debug
print("position 2")
ret <- inVar1
}
#debug
print("position 3")
return(ret)
}
简单功能测试:
> a <- test2(7,1)
[1] "Row=1 inVar1=7"
[1] "position 2"
[1] "position 3"
> print(a)
[1] 7
>
> a <- test2(NA,1)
[1] "Row=1 inVar1=NA"
[1] "position 1"
[1] "position 3"
> print(a)
[1] -100
它按预期工作。
现在让我们创建一个数据框
> d1 <- data.frame(rowID=c(1,2,3), var1=c(2,NA,5))
> print(d1)
rowID var1
1 1 2
2 2 NA
3 3 5
让我们测试从数据帧传递值的函数:
> a <- test2(d1[1,2],d1[1,1])
[1] "Row=1 inVar1=2"
[1] "position 2"
[1] "position 3"
> print(a)
[1] 2
> a <- test2(d1[2,2],d1[2,1])
[1] "Row=2 inVar1=NA"
[1] "position 1"
[1] "position 3"
> print(a)
[1] -100
> a <- test2(d1[3,2],d1[3,1])
[1] "Row=3 inVar1=5"
[1] "position 2"
[1] "position 3"
> print(a)
[1] 5
再次,它按预期工作。
现在,最后一件事。 我想用处理后的值添加一个新列。
d1$var2 <- test2(d1$var1,d1$rowID)
print(d1)
这将产生以下输出:
> d1$var2 <- test2(d1$var1,d1$rowID)
[1] "Row=1 inVar1=2" "Row=2 inVar1=NA" "Row=3 inVar1=5"
[1] "position 2"
[1] "position 3"
> print(d1)
rowID var1 var2
1 1 2 2
2 2 NA NA
3 3 5 5
第1行和第3行中var2的值按预期计算,但在第2行中为NA,而不是预期的-100。
我做错了什么?
我不明白的另一件事是,为什么我们只看到调试消息一次,却看不到行数,即三次?
谢谢!
您的函数未向量化。 您通过1对数字3次,每行一次,这是正确的,而最终测试一次通过1对向量。 每个变量1个向量。 为了使您的功能正常工作,您需要一次喂入一对。 mapply将为您做到这一点。
d1$var2 <- mapply(FUN = test2,inVar1 = d1$var1,inRow = d1$rowID)
但是总的来说,您可能需要考虑向量化来重写函数。
# "vectorised in the sense that it can operate on entire vectors at once"
test2vectbasic <- function(inVar1,inRow){
# using mapply, but could be a basic for loop too
mapply(FUN = test2,inVar1 = inVar1,inRow = inRow)
}
# efficient R vectorization that uses built in low level language loops
# using "existing R functions that are already vectorised"
test2vectbetter <- function(inVar1){
ifelse(is.na(inVar1) | is.null(inVar1),-100,inVar1)
}
# sample data
d1 <- data.frame(rowID=c(1,2,3), var1=c(2,NA,5))
# mapply way
d1$var2 <- mapply(FUN = test2,inVar1 = d1$var1,inRow = d1$rowID)
# basic way on atoms or vectors
test2vectbasic(d1[2,2],d1[2,1])
d1$var3 <- test2vectbasic(d1$var1,d1$rowID)
# efficient way
test2vectbetter(d1[2,2],d1[2,1])
d1$var4 <- test2vectbetter(d1$var1)
要获得所需的功能,至少需要基本的向量化。 关于矢量化的一些资源:
R inferno-转到地狱的第三圈-无法向量化
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.