interpolation/lookup 在 R 中
interpolation/lookup in R
我正在从 excel 切换到 R,并且想知道如何在 R 中执行此操作。
我有一个看起来像这样的数据集:
df1<-data.frame(Zipcode=c("7941AH","7941AG","7941AH","7941AZ"),
From=c(2,30,45,1),
To=c(20,38,57,8),
Type=c("even","mixed","odd","mixed"),
GPS=c(12345,54321,11221,22331))
df2<-data.frame(zipcode=c("7914AH", "7914AH", "7914AH", "7914AG","7914AG","7914AZ"),
housenum=c(18, 19, 50, 32, 104,11))
第一个数据集包含邮政编码、门牌号范围(从和到)、类型含义(如果范围包含偶数、奇数或混合门牌号)和 gps 坐标。第二个数据集仅包含地址(邮政编码、门牌号)。
我想做的是查找 df2 的 gps 坐标。例如,邮政编码 7941AG 和门牌号 18(2 到 20 之间的偶数)的地址具有 gps 坐标 12345.
更新:
因为我没有想到数据集的大小对于所选解决方案很重要(我知道,有点天真......)这里有一些额外的信息:
df1 的实际大小是 472.000 个观察值,而 df2 有 110 万个观察值。 df1 中唯一邮政编码的数量为 280.000。我偶然发现了这个 post speed up the loop operation in R
有一些有趣的发现,但我不知道如何将其合并到@josilber
提供的解决方案中
我将循环遍历 df2
中的每个元素,实现检查邮政编码是否匹配以及元素范围是否正确以及 even/odd 是否正确所需的逻辑:
# Clean up data (character zip codes and fix the 7914 vs. 7941 issue in zip codes)
df2<-data.frame(zipcode=c("7941AH", "7941AH", "7941AH", "7941AG","7941AG","7941AZ"),
housenum=c(18, 19, 50, 32, 104,11))
df1$Zipcode <- as.character(df1$Zipcode)
df2$zipcode <- as.character(df2$zipcode)
# Loop to compute the GPS values
sapply(seq(nrow(df2)), function(x) {
m <- df2[x,]
matched <- df1$Zipcode == m$zipcode &
m$housenum >= df1$From &
m$housenum <= df1$To &
(df1$Type == "mixed" |
(df1$Type == "odd" & m$housenum %% 2 == 1) |
(df1$Type == "even" & m$housenum %% 2 == 0))
if (sum(matched) != 1) {
return(NA) # No matches or multiple matches
} else {
return(df1$GPS[matched])
}
})
# [1] 12345 NA NA 54321 NA NA
通过检查,只有 df2
的第一个和第四个元素符合 df1
中的一个规则。
给定大数据框,你最好的选择可能是通过它们的邮政编码合并 df1
和 df2
(也就是从具有相同邮政编码的数据框中获取每一对行),按门牌号条件过滤,去除重复项(df1
中的多个规则匹配的情况),然后存储所有匹配房屋的信息。让我们从您指定大小的示例数据集开始:
set.seed(144)
df1 <- data.frame(Zipcode=sample(1:280000, 472000, replace=TRUE),
From=sample(1:50, 472000, replace=TRUE),
To=sample(51:100, 472000, replace=TRUE),
Type=sample(c("even", "odd", "mixed"), 472000, replace=TRUE),
GPS=sample(1:100, 472000, replace=TRUE))
df2 <- data.frame(zipcode=sample(1:280000, 1.1e6, replace=TRUE),
housenum=sample(1:100, 1.1e6, replace=TRUE))
现在我们可以对 GPS 数据进行高效计算了:
get.gps <- function(df1, df2) {
# Add ID to df2
df2$id <- 1:nrow(df2)
m <- merge(df1, df2, by.x="Zipcode", by.y="zipcode")
m <- m[m$housenum >= m$From &
m$housenum <= m$To &
(m$Type == "mixed" |
(m$Type == "odd" & m$housenum %% 2 == 1) |
(m$Type == "even" & m$housenum %% 2 == 0)),]
m <- m[!duplicated(m$id) & !duplicated(m$id, fromLast=TRUE),]
GPS <- rep(NA, nrow(df2))
GPS[m$id] <- m$GPS
return(GPS)
}
system.time(get.gps(df1, df2))
# user system elapsed
# 16.197 0.561 17.583
这是一个更可接受的运行时间 -- 18 秒,而不是您在我的其他答案的评论中估计的 90 小时!
我正在从 excel 切换到 R,并且想知道如何在 R 中执行此操作。
我有一个看起来像这样的数据集:
df1<-data.frame(Zipcode=c("7941AH","7941AG","7941AH","7941AZ"),
From=c(2,30,45,1),
To=c(20,38,57,8),
Type=c("even","mixed","odd","mixed"),
GPS=c(12345,54321,11221,22331))
df2<-data.frame(zipcode=c("7914AH", "7914AH", "7914AH", "7914AG","7914AG","7914AZ"),
housenum=c(18, 19, 50, 32, 104,11))
第一个数据集包含邮政编码、门牌号范围(从和到)、类型含义(如果范围包含偶数、奇数或混合门牌号)和 gps 坐标。第二个数据集仅包含地址(邮政编码、门牌号)。
我想做的是查找 df2 的 gps 坐标。例如,邮政编码 7941AG 和门牌号 18(2 到 20 之间的偶数)的地址具有 gps 坐标 12345.
更新: 因为我没有想到数据集的大小对于所选解决方案很重要(我知道,有点天真......)这里有一些额外的信息: df1 的实际大小是 472.000 个观察值,而 df2 有 110 万个观察值。 df1 中唯一邮政编码的数量为 280.000。我偶然发现了这个 post speed up the loop operation in R 有一些有趣的发现,但我不知道如何将其合并到@josilber
提供的解决方案中我将循环遍历 df2
中的每个元素,实现检查邮政编码是否匹配以及元素范围是否正确以及 even/odd 是否正确所需的逻辑:
# Clean up data (character zip codes and fix the 7914 vs. 7941 issue in zip codes)
df2<-data.frame(zipcode=c("7941AH", "7941AH", "7941AH", "7941AG","7941AG","7941AZ"),
housenum=c(18, 19, 50, 32, 104,11))
df1$Zipcode <- as.character(df1$Zipcode)
df2$zipcode <- as.character(df2$zipcode)
# Loop to compute the GPS values
sapply(seq(nrow(df2)), function(x) {
m <- df2[x,]
matched <- df1$Zipcode == m$zipcode &
m$housenum >= df1$From &
m$housenum <= df1$To &
(df1$Type == "mixed" |
(df1$Type == "odd" & m$housenum %% 2 == 1) |
(df1$Type == "even" & m$housenum %% 2 == 0))
if (sum(matched) != 1) {
return(NA) # No matches or multiple matches
} else {
return(df1$GPS[matched])
}
})
# [1] 12345 NA NA 54321 NA NA
通过检查,只有 df2
的第一个和第四个元素符合 df1
中的一个规则。
给定大数据框,你最好的选择可能是通过它们的邮政编码合并 df1
和 df2
(也就是从具有相同邮政编码的数据框中获取每一对行),按门牌号条件过滤,去除重复项(df1
中的多个规则匹配的情况),然后存储所有匹配房屋的信息。让我们从您指定大小的示例数据集开始:
set.seed(144)
df1 <- data.frame(Zipcode=sample(1:280000, 472000, replace=TRUE),
From=sample(1:50, 472000, replace=TRUE),
To=sample(51:100, 472000, replace=TRUE),
Type=sample(c("even", "odd", "mixed"), 472000, replace=TRUE),
GPS=sample(1:100, 472000, replace=TRUE))
df2 <- data.frame(zipcode=sample(1:280000, 1.1e6, replace=TRUE),
housenum=sample(1:100, 1.1e6, replace=TRUE))
现在我们可以对 GPS 数据进行高效计算了:
get.gps <- function(df1, df2) {
# Add ID to df2
df2$id <- 1:nrow(df2)
m <- merge(df1, df2, by.x="Zipcode", by.y="zipcode")
m <- m[m$housenum >= m$From &
m$housenum <= m$To &
(m$Type == "mixed" |
(m$Type == "odd" & m$housenum %% 2 == 1) |
(m$Type == "even" & m$housenum %% 2 == 0)),]
m <- m[!duplicated(m$id) & !duplicated(m$id, fromLast=TRUE),]
GPS <- rep(NA, nrow(df2))
GPS[m$id] <- m$GPS
return(GPS)
}
system.time(get.gps(df1, df2))
# user system elapsed
# 16.197 0.561 17.583
这是一个更可接受的运行时间 -- 18 秒,而不是您在我的其他答案的评论中估计的 90 小时!