在数据框中有条件地(2 个条件)更改值并避免 R 中的循环
Change value conditionally (2 conditions) in a data frame and avoid loops in R
我有一种情况,我目前使用非常耗时的循环。
我的数据集:
SPECIE(3 列 data.frame);
世界(3 列矩阵)
在 SPECIE 中,我有 3 个变量:LAT、LON、OCC(数字)
OCC 总是 > 0。SPECIE 包含发现物种的位置,以及发现的次数(在 OCC 中)。
SPECIE的长度一般在3000左右
在WORLD中,我有世界上所有的经纬度(grid -180 to 180, -90 to 90, res 0.5)
因此,在 WORLD 中,我有:LAT、LON、OCC
OCC 通常为 0。WORLD 的长度为 259200 (180 * 2 * 360 * 2) x 3columns
我的目标:在发现该物种的世界中修改 OCC。最后,我拥有了世界上所有的 latitudes/longitudes,以及是否在精确的 lat/lon 对中找到了该物种的信息。
目前,我是:
for(j in 1:259200)
{
for(k in 1:length(SPECIE$OCC))
{
if((SPECIE$LON[k] == WORLD[j,1]) & (SPECIE$LAT[k] == WORLD[j,2]))
{
WORLD[j,3] <- SPECIE$OCC[k]
}
}
}
我寻找没有循环的解决方案(需要几个小时),但没有找到有效的方法。
头数:
> head(WORLD)
[,1] [,2] [,3]
[1,] -179.75 -89.75 0
[2,] -179.75 -89.25 0
[3,] -179.75 -88.75 0
[4,] -179.75 -88.25 0
> head(SPECIE)
LON LAT OCC
1 -89.75 24.75 1
2 -89.75 25.25 1
3 -89.75 25.75 6
4 -89.75 26.25 45
非常感谢!
如果您发布一些示例数据会有所帮助,但试试这个:
world.df <- as.data.frame(world)
names(world) <- names(specie)
matches <- which(world.df$lat %in% specie$lat & world.df$lon %in% specie$lon)
world.df$occ[matches] <- merge(specie, world.df, by=c('lat', 'lon'))$occ.x
令人惊叹的 data.table
软件包是您的朋友,它会在眨眼间完成这项工作。
由于你没有提供数据,我模拟了一些,SPECIE中的LAT和LON值都包含在WORLD中的同一个坐标中,但也有WORLD中的值没有包含在SPECIE中。我为 LAT 和 LON 编了非常规则的值,但使用真实数据,它应该以相同的方式工作。
require(data.table)
# set lengths for example
nSPECIE <- 5
nWORLD <- 10
# simulate the SPECIE data, from data.frame to data.table
SPECIE <- data.frame(LAT = 1:nSPECIE,
LON = 1:nSPECIE,
OCC_specie = 1:nSPECIE)
SPECIE <- as.data.table(SPECIE)
# simulate the WORLD data, from matrix to data.table
WORLD <- matrix(c(1:nWORLD,
1:nWORLD,
rpois(nWORLD, 1)),
ncol = 3,
dimnames = list(NULL, c("LAT", "LON", "OCC_world")))
WORLD <- as.data.table(WORLD)
# merge
setkey(SPECIE, LAT, LON)
setkey(WORLD, LAT, LON)
WORLD_modified <- SPECIE[WORLD]
## LAT LON OCC_specie OCC_world
## 1: 1 1 1 0
## 2: 2 2 2 2
## 3: 3 3 3 2
## 4: 4 4 4 0
## 5: 5 5 5 0
## 6: 6 6 NA 1
## 7: 7 7 NA 0
## 8: 8 8 NA 2
## 9: 9 9 NA 2
## 10: 10 10 NA 3
如您所见,SPECIE 中的 OCC 值现在已匹配,并且 WORLD 中在 SPECIE 中没有相应记录的位置被赋予 SPECIE 中 OCC 列的 NA 值。
只是为了向您展示有多快,您可以调高参数:
# with original sizes
nSPECIE <- 3000
nWORLD <- 259000
SPECIE <- data.frame(LAT = 1:nSPECIE,
LON = 1:nSPECIE,
OCC_specie = 1:nSPECIE)
SPECIE <- as.data.table(SPECIE)
WORLD <- matrix(c(1:nWORLD,
1:nWORLD,
rpois(nWORLD, 1)),
ncol = 3,
dimnames = list(NULL, c("LAT", "LON", "OCC_world")))
WORLD <- as.data.table(WORLD)
setkey(SPECIE, LAT, LON)
setkey(WORLD, LAT, LON)
system.time(WORLD_modified <- SPECIE[WORLD])
## user system elapsed
## 0.003 0.000 0.004
阅读data.table
vignette and manual,如果您需要匹配表格,这是非常值得投入的时间。优秀的 dplyr
包也利用了这个,但我更喜欢直接 data.table
来完成这样的工作。
我有一种情况,我目前使用非常耗时的循环。
我的数据集: SPECIE(3 列 data.frame); 世界(3 列矩阵)
在 SPECIE 中,我有 3 个变量:LAT、LON、OCC(数字) OCC 总是 > 0。SPECIE 包含发现物种的位置,以及发现的次数(在 OCC 中)。 SPECIE的长度一般在3000左右
在WORLD中,我有世界上所有的经纬度(grid -180 to 180, -90 to 90, res 0.5) 因此,在 WORLD 中,我有:LAT、LON、OCC OCC 通常为 0。WORLD 的长度为 259200 (180 * 2 * 360 * 2) x 3columns
我的目标:在发现该物种的世界中修改 OCC。最后,我拥有了世界上所有的 latitudes/longitudes,以及是否在精确的 lat/lon 对中找到了该物种的信息。
目前,我是:
for(j in 1:259200)
{
for(k in 1:length(SPECIE$OCC))
{
if((SPECIE$LON[k] == WORLD[j,1]) & (SPECIE$LAT[k] == WORLD[j,2]))
{
WORLD[j,3] <- SPECIE$OCC[k]
}
}
}
我寻找没有循环的解决方案(需要几个小时),但没有找到有效的方法。
头数:
> head(WORLD)
[,1] [,2] [,3]
[1,] -179.75 -89.75 0
[2,] -179.75 -89.25 0
[3,] -179.75 -88.75 0
[4,] -179.75 -88.25 0
> head(SPECIE)
LON LAT OCC
1 -89.75 24.75 1
2 -89.75 25.25 1
3 -89.75 25.75 6
4 -89.75 26.25 45
非常感谢!
如果您发布一些示例数据会有所帮助,但试试这个:
world.df <- as.data.frame(world)
names(world) <- names(specie)
matches <- which(world.df$lat %in% specie$lat & world.df$lon %in% specie$lon)
world.df$occ[matches] <- merge(specie, world.df, by=c('lat', 'lon'))$occ.x
令人惊叹的 data.table
软件包是您的朋友,它会在眨眼间完成这项工作。
由于你没有提供数据,我模拟了一些,SPECIE中的LAT和LON值都包含在WORLD中的同一个坐标中,但也有WORLD中的值没有包含在SPECIE中。我为 LAT 和 LON 编了非常规则的值,但使用真实数据,它应该以相同的方式工作。
require(data.table)
# set lengths for example
nSPECIE <- 5
nWORLD <- 10
# simulate the SPECIE data, from data.frame to data.table
SPECIE <- data.frame(LAT = 1:nSPECIE,
LON = 1:nSPECIE,
OCC_specie = 1:nSPECIE)
SPECIE <- as.data.table(SPECIE)
# simulate the WORLD data, from matrix to data.table
WORLD <- matrix(c(1:nWORLD,
1:nWORLD,
rpois(nWORLD, 1)),
ncol = 3,
dimnames = list(NULL, c("LAT", "LON", "OCC_world")))
WORLD <- as.data.table(WORLD)
# merge
setkey(SPECIE, LAT, LON)
setkey(WORLD, LAT, LON)
WORLD_modified <- SPECIE[WORLD]
## LAT LON OCC_specie OCC_world
## 1: 1 1 1 0
## 2: 2 2 2 2
## 3: 3 3 3 2
## 4: 4 4 4 0
## 5: 5 5 5 0
## 6: 6 6 NA 1
## 7: 7 7 NA 0
## 8: 8 8 NA 2
## 9: 9 9 NA 2
## 10: 10 10 NA 3
如您所见,SPECIE 中的 OCC 值现在已匹配,并且 WORLD 中在 SPECIE 中没有相应记录的位置被赋予 SPECIE 中 OCC 列的 NA 值。
只是为了向您展示有多快,您可以调高参数:
# with original sizes
nSPECIE <- 3000
nWORLD <- 259000
SPECIE <- data.frame(LAT = 1:nSPECIE,
LON = 1:nSPECIE,
OCC_specie = 1:nSPECIE)
SPECIE <- as.data.table(SPECIE)
WORLD <- matrix(c(1:nWORLD,
1:nWORLD,
rpois(nWORLD, 1)),
ncol = 3,
dimnames = list(NULL, c("LAT", "LON", "OCC_world")))
WORLD <- as.data.table(WORLD)
setkey(SPECIE, LAT, LON)
setkey(WORLD, LAT, LON)
system.time(WORLD_modified <- SPECIE[WORLD])
## user system elapsed
## 0.003 0.000 0.004
阅读data.table
vignette and manual,如果您需要匹配表格,这是非常值得投入的时间。优秀的 dplyr
包也利用了这个,但我更喜欢直接 data.table
来完成这样的工作。