两个数据帧之间的多重比较,而不使用“for”

时间:2017-08-08 11:05:29

标签: r dataframe dplyr comparison

我有两个数据帧(df1df2),结果为guest_idmoneydate

我想通过使用这些来确定第一个数据帧中的元素是否也在第二个数据帧中。为此,我希望使用我将在df1中添加的变量,并且我将命名为{{ 1}},如果match中的元素也在df1中,则取1,否则为0

但是它们不完全匹配(因为报告中有一些错误),所以我不能简单地将它们合并为这3列或类似的东西

因此,我想知道:

进行一些简单的比较
  • guest_id比较没有错误,因此我想检查df2的{​​{1}}与guest_id的{​​{1}}匹配
  • 警告:guest_id可以在数据框中多次出现
  • 当访客位于df1guest_id时,我想检查df2df1。我想这样做:
    • 对于df2 money,对于给定date的{​​{1}} moneymoney中可能出现的所有df1之间的差异(但仅限于给定的guest_id)。如果发生的事件接近0(在-1和1之间,或money 1,如果我使用df2),那么我认为guest_id匹配
    • <=:我做的事情与abs()相同;我认为如果money中的date介于money之间; date,然后df1匹配(再次,我想仅针对给定的df2$date - 5进行这些比较,而不查看整个数据帧,否则它可能与df2$date + 5date,但对于另一位客人,这就是我遇到的问题)
  • 因此,如果我匹配guest_idmoneydate,我可以在我的guest_id变量中加1,否则它是0 < / LI>

我使用money,但由于我是初学者,因此无法找到正确使用的函数序列。我也宁愿避免使用date,因为我正在处理大型数据帧,因此获取结果肯定会花费太多时间

总结一下,这就是我所拥有的:

match

结果:

dplyr

有没有人知道如何做到这一点(甚至是这个问题的完全不同的方法)?

2 个答案:

答案 0 :(得分:1)

我建议先进行左连接,然后应用条件并查找df1中的任何原始行是否匹配:

library('stringr')
library('dplyr')

df3 <- left_join(df1, df2, by = 'guest_id') %>%
  mutate_at(vars(contains('date')), ymd) %>%
  # Checking for your condition
  mutate(match = (abs(money.x - money.y) < 1) & (abs(date.x - date.y) < 5)) %>%
  # Cleaning data.frame a bit
  select(-money.y, -date.y) %>%
  setNames(str_replace(names(.), '\\.x', '')) %>%
  # Finding if rows had a match
  group_by(guest_id, money, date) %>%
  summarise(match = any(match, na.rm = TRUE))

df3
# A tibble: 6 x 4
# Groups:   guest_id, money [?]
  guest_id money       date match
     <int> <dbl>     <date> <lgl>
1        1  10.2 2017-01-01  TRUE
2        1  10.3 2000-01-01 FALSE
3        1  50.0 2017-01-01 FALSE
4        2   9.5 2017-01-01  TRUE
5        2  10.5 2017-01-01  TRUE
6        3 100.0 2000-01-01 FALSE

data.frame我曾用于测试:

df1 <- structure(list(guest_id = c(1L, 1L, 1L, 2L, 2L, 3L), money = c(10.2, 
10.3, 50, 10.5, 9.5, 100), date = c("2017-01-01", "2000-01-01", 
"2017-01-01", "2017-01-01", "2017-01-01", "2000-01-01")), .Names = c("guest_id", 
"money", "date"), class = "data.frame", row.names = c(NA, -6L
))

df2 <- structure(list(guest_id = c(1L, 1L, 2L), money = c(10L, 10L, 
10L), date = c("2017-01-01", "2015-01-01", "2017-01-03")), .Names = c("guest_id", 
"money", "date"), class = "data.frame", row.names = c(NA, -3L
))

答案 1 :(得分:1)

最近版本的data.table支持非equi 加入非常方便和有效,特别是与加入上的更新和{{{ 1}}:

.EACHI
library(data.table)   # CRAN version 1.10.4 used
# tolerances
tol_m <- 1
tol_d <- 5

data.table(df1)[
  # join with modified df2
  data.table(df2)[
    # create helper columns for non-equi joins
    , `:=`(m1 = money - tol_m, m2 = money + tol_m, 
           d1 = date - tol_d, d2 = date + tol_d)]
  # non-equi join
  , on = c("guest_id", "money>=m1", "money<=m2", "date>=d1", "date<=d2"), 
  # aggregate group-wise, grouped by join conditions, prettify result
  match := .N, by = .EACHI][, match := as.integer(!is.na(match))][]

如果没有非等联接,我们将不得不创建所有可能组合的笛卡尔积,并消除那些与条件不匹配的行。