我有一个参考数据框架(df1),包含三列“特性”(性别、年份、代码)和两列“值”(数量、状态)。它看起来像这样,但是有很多行:
gender year code amount status
M 2011 A 15 EMX
M 2011 A 123 NOX
F 2015 B 0 MIX
F 2018 A 12 NOX
F 2015 B 11 NOX我有另一个数据框架(df2),它只有三个“特性”列。例如:
gender year code
M 2011 A
M 2011 A
F 2018 A
F 2015 B对于df2中的每一行,我想根据“特征”中的匹配将“值”赋给df1。在有多个匹配的地方,我想随机选择“值”对。因此,当df2中存在重复的“特性”时,它们可能会以不同的“值”对结束,但它们在df1中都将完全匹配。本质上,对于每个特征组合,我希望值的分布在两个表之间匹配。
例如,'df2‘中的最后一行(性别= F,年份=2015年,代码= B)匹配’df1‘中的两行:第三行(amont = 0,status = MIX)和第五行( and = 11,status = NOX)。然后,应随机选择这些匹配行之一。对于基于性别、年份和代码的“df2”和“df1”之间的多个匹配情况,应该选择一个随机行。
到目前为止,我的方法是从使用dplyr在两个数据帧之间执行left_join开始。但是,这为df2中的每一行提供了所有可能的“值”,而不是随机选择一个。因此,我必须根据特征进行分组,并选择一个。这会产生一个非常大的中间表,而且看起来效率不高。
我想知道是否有人有更有效的方法的建议?我以前发现加入data.table包会更快,但是对这个包没有很好的理解。我还想知道我是应该做联接呢,还是应该只使用sample函数?
任何帮助都很感激。
发布于 2019-06-12 12:31:51
使用“d2”根据“性别”、“年份”、“代码”(d1[d2, on = .(gender, year, code), ...])中的匹配查找“d1”中的行。对于每个匹配(by = .EACHI),示例一行(sample(.N, 1L))。用这个来索引“金额”和“状态”。
d1[d2, on = .(gender, year, code),
{ri <- sample(.N, 1L)
.(amount = amount[ri], status = status[ri])}, by = .EACHI]
# sample based on set.seed(1)
# gender year code amount status
# 1: M 2011 A 15 EMX
# 2: M 2011 A 15 EMX
# 3: F 2018 A 12 NOX
# 4: F 2015 B 11 NOX请注意,论据上有一个悬而未决的问题,即当x中的多行与i中的行匹配时,如何处理情况。目前,有效的选项是"all" (默认)、"first"或"last"。但是,如果/当问题实现时,可以使用mult = "random" (sample(.N, size = 1L))在匹配中选择随机行(行)。
发布于 2019-06-12 11:58:01
df2 %>%
mutate(
amount = pmap_chr(
.l = df2,
.f = ~ df1 %>%
filter(gender == ..1, year == ..2, code == ..3) %>%
select(amount) %>%
sample_n(1) %>%
pull(amount)
),
status = pmap_chr(
.l = df2,
.f = ~ df1 %>%
filter(gender == ..1, year == ..2, code == ..3) %>%
select(status) %>%
sample_n(1) %>%
pull(status)
)
)这是相当缓慢的,我个人会避免它,但这是一种方法。
发布于 2019-06-12 11:58:26
我希望这样做是有效率的:
df1[, row := .I]
keys <- c("year", "gender", "code")
setkeyv(df1, keys)
setkeyv(df2, keys)
for (rowdf2 in seq_len(nrow(df2))) {
set(df2, i = rowdf2, j = "rowindf1", value = df1[df2[rowdf2], x.row[sample(.N, 1)]])
}
setkeyv(df1, "row")
df1[df2[, .(rowindf1)]]示例输出:
# gender year code amount status row
# 1: M 2011 A 123 NOX 2
# 2: M 2011 A 15 EMX 1
# 3: F 2015 B 11 NOX 5
# 4: F 2018 A 12 NOX 4https://stackoverflow.com/questions/56559559
复制相似问题