我需要对数百万行数据应用优化函数,该函数根据两个输入变量返回一个数字。使用 mapply 应用该函数需要很长时间。由于数据中的值范围有限且有大量重复,因此我认为为可能的输入组合的整个范围创建一个查找表会更快,然后只需使用 dplyr 的联接来填充数据。由于查找表(实际上是数据框)中的一些奇怪行为,我的尝试失败了。下面是一个可重复的示例。我试图理解为什么我无法引用查找表中的某些值,但其他值可以正常工作。
## build a lookup table with three columns
lookup <- transform(expand.grid(0:180, seq(0, 35, by=0.1)), v=0)
colnames(lookup) <- c("d", "s", "v")
lookup$v <- 1:nrow(lookup)
## generate some fake data with random values
set.seed(42) ## for sake of reproducibility
data <- data.frame(d=sample(lookup$d, 1000, replace=TRUE),
s=round(runif(n=1000, min=0, max=35), 1))
## left join gives a lot of NAs
joined <- dplyr::left_join(x=data, y=lookup, by=c('d', 's'))
joined[1:20, ]
# d s v
# 1 53 5.3 NA
# 2 124 20.2 NA
# 3 172 21.5 39088
# 4 137 5.3 NA
# 5 52 18.8 34081
# 6 67 20.0 36268
# 7 87 21.1 38279
# 8 64 29.4 NA
# 9 97 18.5 33583
# 10 159 8.6 15726
# 11 40 10.4 18865
# 12 138 29.6 53715
# 13 33 15.7 NA
# 14 171 24.4 NA
# 15 126 33.2 60219
# 16 120 20.1 36502
# 17 15 17.3 31329
# 18 104 17.4 NA
# 19 34 3.3 NA
# 20 92 33.6 60909
## unable to reference certain values...
lookup$v[which(lookup$d == 177 & lookup$s == 8.2)]
#integer(0)
## ...even though they exist
lookup[15020,]
# d s v
#15020 177 8.2 15020
## other values are OK
lookup$v[which(lookup$d == 177 & lookup$s == 8.3)]
#[1] 15201
您可以使用
merge(., sort=FALSE)
来获得您想要的结果。
> joined <- merge(data, lookup, sort=FALSE)
> joined[1:20, ]
d s v
1 81 23.8 43160
2 67 15.1 27399
3 158 28.4 51563
4 11 31.5 57027
5 69 30.4 55094
6 62 14.5 26308
7 99 25.0 45350
8 136 26.6 48283
9 92 24.8 44981
10 25 11.0 19936
11 35 20.8 37684
12 88 13.8 25067
13 83 18.0 32664
14 43 14.1 25565
15 133 7.3 13347
16 48 34.5 62494
17 46 34.5 62492
18 16 33.9 61376
19 145 7.5 13721
20 69 13.9 25229
对于你的第二个问题,请注意,你正在处理浮点精度,因此没有得到你期望的结果,
> lookup[15020, ]
d s v
15020 177 8.2 15020
> lookup$s[15020] == 8.2
[1] FALSE
在这个答案中阅读更多相关信息。