R 两个数据帧之间的多次比较,而不使用;至于;
我有两个数据帧(R 两个数据帧之间的多次比较,而不使用;至于;,r,dataframe,dplyr,comparison,R,Dataframe,Dplyr,Comparison,我有两个数据帧(df1和df2),结果是guest\u id、money、和date 我想通过使用这3个参数来确定第一个数据帧中的元素是否也在第二个数据帧中。为此,我希望使用一个变量,我将在df1中添加该变量,并将其命名为match,如果df1中的元素也在df2中,则取1,否则取0 但是,它们并不完全匹配(因为报告中有一些错误),所以我不能简单地通过这3列或类似的内容来合并它们 因此,我想做一些简单的比较,知道: 来宾id比较没有错误,因此我想检查df1的来宾id何时与df2的来宾id匹配 警
df1
和df2
),结果是guest\u id
、money
、和date
我想通过使用这3个参数来确定第一个数据帧中的元素是否也在第二个数据帧中。为此,我希望使用一个变量,我将在df1
中添加该变量,并将其命名为match
,如果df1
中的元素也在df2
中,则取1,否则取0
但是,它们并不完全匹配(因为报告中有一些错误),所以我不能简单地通过这3列或类似的内容来合并它们
因此,我想做一些简单的比较,知道:
- 来宾id比较没有错误,因此我想检查
df1的
何时与来宾id
df2的
匹配来宾id
- 警告:来宾id可能会在数据框中出现多次
- 当客人在
和df1
时,我想检查df2
钱和
日期。我想这样做:
- 对于
而言,将money
中的df1
钱与
中可能出现的所有df2
进行区分(但同样仅针对给定的钱
)。如果出现接近0的情况(介于-1和1之间,或来宾id
),我建议先进行左连接,然后应用您的条件并查找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
最新版本的
支持非常方便和高效的非相等联接,尤其是与联接更新和分组方式data.table
:相结合。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))][]
如果没有非等联接,我们将不得不创建所有可能组合的笛卡尔积,并消除那些不符合条件的行。看看
包,尽管我确信使用了两个合并列(其中一个是模糊列,另一个不是)这是可能的。谢谢!乍一看,它似乎确实可以帮助我尝试的Lotineded,而且显然比使用Andrey的方法快得多(尽管两者都很好)。非常感谢!如果fuzzyjoin
或df1
是大对象,如果使用df2
而不是setDT()
。后者复制时保留原始数据。帧不变,而data.table(),您可以保护内存和时间
强制到位,即不复制,复制速度更快,但会更改setDT()
和df1
。df2
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
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 ))
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))][]
guest_id money date match 1: 1 10.2 2017-01-01 1 2: 1 10.3 2000-01-01 0 3: 1 50.0 2017-01-01 0 4: 2 10.5 2017-01-01 1 5: 2 9.5 2017-01-01 1 6: 3 100.0 2000-01-01 0
- 对于