rey*_*n64 3 r transform lapply dataframe
我需要使用R*apply函数为初学者制作教程(第一次不使用reshape或plyr包)
我尝试lapply(因为我读取apply数据帧不好)这个数据帧的简单函数,我想使用命名列来访问数据:
fDist <- function(x1,x2,y1,y2) {
return (0.1*((x1 - x2)^2 + (y1-y2)^2)^0.5)
}
data <- read.table(textConnection("X1 Y1 X2 Y2
1 3.5 2.1 4.1 2.9
2 3.1 1.2 0.8 4.3
"))
data$dist <- lapply(data,function(df) {fDist(df$X1 , df$X2 , df$Y1 , df$Y2)})
Run Code Online (Sandbox Code Playgroud)
我有这个错误$ operator is invalid for atomic vectors,可能是因为数据帧是通过laply修改的?...有没有一个最好的方法来使用$ named列?
我用@DWin回答我的第一个问题.但我有另一个问题,误解,混合数据帧(数字+字符):
在我的新用例中,我使用两个函数来计算距离,因为我的目标是比较所有其他Point之间的距离Point.
data2 <- read.table(textConnection("X1 Y1 X2 Y2
1 3.5 2.1 4.1 2.9
2 3.1 1.2 0.8 4.3
"))
data2$char <- c("a","b")
fDist <- function(x1,y1,x2,y2) {
return (0.1*((x1 - x2)^2 + (y1-y2)^2)^0.5)
}
fDist2 <- function(fixedX,fixedY,vec) {
fDist(fixedX,fixedY,vec[['X2']],vec[['Y2']])
}
# works with data (dataframe without character), but not with data2 (dataframe with character)
#ok
data$f_dist <- apply(data, 1, function(df) {fDist2(data[1,]$X1,data[1,]$Y1,df)})
#not ok
data2$f_dist <- apply(data2, 1, function(df) {fDist2(data2[1,]$X1,data2[1,]$Y1,df)})
Run Code Online (Sandbox Code Playgroud)
在这种情况下apply,你需要的.所有数据列都属于同一类型,您不必担心丢失属性,这是应用导致问题的地方.您将需要以不同的方式编写函数,因此它只需要一个长度为4的向量:
fDist <- function(vec) {
return (0.1*((vec[1] - vec[2])^2 + (vec[3]-vec[4])^2)^0.5)
}
data$f_dist <- apply(data, 1, fDist)
data
X1 Y1 X2 Y2 f_dist
1 3.5 2.1 4.1 2.9 0.1843909
2 3.1 1.2 0.8 4.3 0.3982462
Run Code Online (Sandbox Code Playgroud)
如果你想使用'data'中列的名称,那么它们需要拼写正确:
fDist <- function(vec) {
return (0.1*((vec['X1'] - vec['X2'])^2 + (vec['Y1']-vec['Y2'])^2)^0.5)
}
data$f_dist <- apply(data, 1, fDist)
data
#--------
X1 Y1 X2 Y2 f_dist
1 3.5 2.1 4.1 2.9 0.1000000
2 3.1 1.2 0.8 4.3 0.3860052
Run Code Online (Sandbox Code Playgroud)
您更新(和非常不同)的问题很容易解决.当你使用apply它时强制使用最低共模分母,在这种情况下是'character'.您有两个选择:1)添加as.numeric到函数内的所有参数,或2)仅发送我将要说明的所需列:
data2$f_dist <- apply(data2[ , c("X2", "Y2") ], 1, function(coords)
{fDist2(data2[1,]$X1,data2[1,]$Y1, coords)} )
Run Code Online (Sandbox Code Playgroud)
我真的不喜欢你如何将参数传递给这个函数.在形式列表中使用"["和"$""只是看起来不对." 你应该知道"df"不是数据帧,而是矢量.因为它不是数据帧(或列表),所以你应该改变里面的函数,使它使用"["而不是"[[".由于您只需要两个坐标,因此只传递您将使用的两个(数字)坐标.
作为旁注,通常,最好避免使用data作为变量名,因为它在基R中的函数:
dat <- read.table(textConnection("X1 Y1 X2 Y2
1 3.5 2.1 4.1 2.9
2 3.1 1.2 0.8 4.3
"))
Run Code Online (Sandbox Code Playgroud)
lapply 将data.frame的单列提供给函数.
lapply(dat, function(df) print(df))
Run Code Online (Sandbox Code Playgroud)
相反,你想要apply.但它将一行作为向量提供,而不使用$运算符.相反,您可以直接索引:
apply(dat, 1, function(vec) {fDist(vec[1] , vec[3] , vec[2] , vec[4])})
Run Code Online (Sandbox Code Playgroud)
或者重写函数以将位置参数作为附加参数.
fDist <- function(vec, pos1, pos2, pos3, pos4) {
return (0.1*((vec[pos1] - vec[pos2])^2 + (vec[pos3]-vec[pos4])^2)^0.5)
}
apply(dat, 1, fDist, pos1=1, pos2=3, pos3 = 2, pos4=4)
Run Code Online (Sandbox Code Playgroud)
但是,最好的解决方案是完全矢量化您的函数:
fDist <- function(df) {
return (0.1*((df$X1 - df$X2)^2 + (df$Y1-df$Y2)^2)^0.5)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8821 次 |
| 最近记录: |