我有以下两个数据框:
df1 <- data.frame(group = rep("A", 5),
name = c("Brandon",
"Kyler",
"Trent",
"Lesa",
"Michael"),
gender = c("M", "F", "M", "F", "M"),
days = c(50, 45, 32, 60, 48))
df2 <- data.frame(group = rep("B", 10),
name = c("Erica",
"Jared",
"Sara",
"Helen",
"Tom",
"Ron",
"Cy",
"Lynn",
"Ken",
"Judy"),
gender = c("F", "M", "F", "F", "M", "M", "M", "F", "M", "F"),
days = c(47, 49, 62, 80, 74, 30, 55, 58, 63, 25))
我想根据 gender
和 过滤
,优先考虑df2
以仅包含与 df1
数据框中的每一行最接近的匹配项天性别
。
例如,在 df1
中,“Brandon”有 gender == M
和 days == 50
。当我们只查看 df2
中的 gender == M
时,我们看到“Jared”在天数上最接近“Brandon”,因此“Jared”将被选为“布兰登”比赛。总的来说,生成的数据框如下所示:
# group name gender days
# B Jared M 49
# B Erica F 47
# B Ron M 30
# B Lynn F 58
# B Cy M 55
附加规则:
这是一个分层合并,其中
gender
匹配优先于days
接近度。请注意,
df1
中有两个等距选项可匹配“Lesa”(“Sara”和“Lynn”)。随机选择两者之一来匹配“Lesa”。在上面的最终数据框中,示例选择了“Lynn”。df2
中的“Jared”与df1
中的“Brandon”和“Michael”距离相等。因为“Jared”已经匹配到“Brandon”,所以他不能再匹配到“Michael”。因此,与“Michael”的比赛继续进行到“Cy”,这是在gender
和days
方面的下一个最佳剩余比赛。
最佳答案
数据
首先,我将 stringsAsFactors = FALSE
添加到您的输入数据框中,因为在我的解决方案中使用字符串比使用因子更容易。
df1 <- data.frame(group = rep("A", 5),
name = c("Brandon",
"Kyler",
"Trent",
"Lesa",
"Michael"),
gender = c("M", "F", "M", "F", "M"),
days = c(50, 45, 32, 60, 48),
stringsAsFactors = FALSE)
df2 <- data.frame(group = rep("B", 10),
name = c("Erica",
"Jared",
"Sara",
"Helen",
"Tom",
"Ron",
"Cy",
"Lynn",
"Ken",
"Judy"),
gender = c("F", "M", "F", "F", "M", "M", "M", "F", "M", "F"),
days = c(47, 49, 62, 80, 74, 30, 55, 58, 63, 25),
stringsAsFactors = FALSE)
解决方案
library(tidyverse)
# empty dataframe for the output
df2_new <- data.frame(group = character(),
name = character(),
gender = character(),
days = numeric(),
stringsAsFactors = FALSE)
for(i in 1:nrow(df1)){
# add the row of interest to the output dataframe
df2_new[i,] <- df2 %>%
mutate(day_diff = abs(days - df1$days[i])) %>%
filter(gender == df1$gender[i]) %>%
slice(which.min(day_diff)) %>%
select(-day_diff)
# remove the newly added row from the original dataset
df2 <- df2 %>%
filter(!(name %in% df2_new$name))
}
这是第一个想到的解决方案。在这种情况下,随着 for 循环的进行,行从 df2
中删除,正如您所说的那样
want to filter
df2
to include only the closest match to each row in thedf1
输出
df2_new
group name gender days
1 B Jared M 49
2 B Erica F 47
3 B Ron M 30
4 B Sara F 62
5 B Cy M 55
在我的例子中,代码选择了 Sara 而不是 Lynn,但这是一个 50/50 的选择。
关于r - 在接近度上匹配两个 R 数据帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54220797/