在数据框中有条件地(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 来完成这样的工作。