我有以下两个数据帧:
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))
我想过滤df2
,使其仅包含与df1
和gender
基于days
的{{1}}数据框中的每一行最接近的匹配项优先。
例如,在gender
中,“布兰登”具有df1
和gender == M
。当我们仅查看days == 50
中的gender == M
时,我们发现“ Jared”在几天之内最接近“ Brandon”,因此将为“ Brandon”匹配选择“ Jared”。总体而言,结果数据框架如下所示:
df2
其他规则:
这是分层合并,其中# 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
中的“ Lesa”匹配(“ Sara”和“ Lynn”)。随机选择两者之一以匹配“ Lesa”。在上面的最后一个数据框中,示例选择了“ Lynn”。
df1
中的“ Jared”与df2
中的“ Brandon”和“ Michael”的距离相等。因为“ Jared”已经与“ Brandon”匹配,所以他也不能与“ Michael”匹配。因此,与“ Michael”的比赛继续至“ Cy”,这是就df1
和gender
而言第二好的比赛。
答案 0 :(得分:2)
首先,我将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
中的行将被删除
想要过滤
df2
,使其仅包含与df1
中每一行最接近的匹配项
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的选择。