sessionInfo-6ren">
gpt4 book ai didi

r - left_join 用于 tbl : na_matches not working

转载 作者:行者123 更新时间:2023-12-03 16:22:44 26 4
gpt4 key购买 nike

left_join在小标题或数据帧上使用 NA 值按预期工作,但在 tbl 上,它似乎与 NA 不匹配,即使使用选项 na_matches = "na"。

R 版本和包版本

> sessionInfo()
R version 3.6.1 (2019-07-05)
Platform: x86_64-apple-darwin18.6.0 (64-bit)
Running under: macOS Mojave 10.14.6
...
other attached packages:
[1] reprex_0.3.0 dbplyr_1.4.2 lubridate_1.7.4 magrittr_1.5 forcats_0.4.0 stringr_1.4.0 dplyr_0.8.1 purrr_0.3.2 readr_1.3.1
[10] tidyr_0.8.3 tibble_2.1.3 ggplot2_3.2.0 tidyverse_1.2.1
...

以下是 SQLite 的一个代表,但 PostgreSQL 也发生了同样的情况(我实际上偶然发现了 PostgreSQL DB 的问题)。

最小的代表。

(1) 我创建了 2 个数据框,将它们本地复制到 SQLite DB,然后将它们再次加载为 tbl。
library(tidyverse)
con <- DBI::dbConnect(RSQLite::SQLite(), ":memory:")
df_1 <- tibble(A = c("a", "aa"), B = c("b", "bb"), D = c("d", NA))
df_2 <- tibble(A = c("a", "aa"), C = c("c", "cc"), D = c("d", NA))
copy_to(con, df_1, overwrite = T)
copy_to(con, df_2, overwrite = T)
dt_1 <- tbl(con, "df_1")
dt_2 <- tbl(con, "df_2")

df_1
#> # A tibble: 2 x 3
#> A B D
#> <chr> <chr> <chr>
#> 1 a b d
#> 2 aa bb <NA>

df_2
#> # A tibble: 2 x 3
#> A C D
#> <chr> <chr> <chr>
#> 1 a c d
#> 2 aa cc <NA>

dt_1
#> # Source: table<df_1> [?? x 3]
#> # Database: sqlite 3.29.0 [:memory:]
#> A B D
#> <chr> <chr> <chr>
#> 1 a b d
#> 2 aa bb <NA>

dt_2
#> # Source: table<df_2> [?? x 3]
#> # Database: sqlite 3.29.0 [:memory:]
#> A C D
#> <chr> <chr> <chr>
#> 1 a c d
#> 2 aa cc <NA>

(2) 然后我用 left_join ,首先在数据帧上,然后在 tbls 上:
left_join(df_1, df_2)
#> Joining, by = c("A", "D")
#> # A tibble: 2 x 4
#> A B D C
#> <chr> <chr> <chr> <chr>
#> 1 a b d c
#> 2 aa bb <NA> cc

left_join(dt_1, dt_2, na_matches = "na")
#> Joining, by = c("A", "D")
#> # Source: lazy query [?? x 4]
#> # Database: sqlite 3.29.0 [:memory:]
#> A B D C
#> <chr> <chr> <chr> <chr>
#> 1 a b d c
#> 2 aa bb <NA> <NA>

我们可以看到第二行最后一列 C有预期的 cc在数据帧的情况下(默认为 na_matches = "na" )但 <NA>在 tbl 的情况下,即使使用显式选项 na_matches = "na" (根据文档,这是默认设置)。 这是出乎意料的 .

编辑

请注意,这与带有 na_matches = "never" 的数据帧的结果相同。 :

left_join(df_1, df_2, na_matches = "never")
#> Joining, by = c("A", "D")
#> # A tibble: 2 x 4
#> A B D C
#> <chr> <chr> <chr> <chr>
#> 1 a b d c
#> 2 aa bb <NA> <NA>

顺便说一句,标题提到 left_join因为它是最常见的连接,但是 inner_join 也会出现同样的问题( full_join 还没有用于数据表),如果我们保留 na_matches = "na" 可能会更加明显同时:
inner_join(dt_1, dt_2, na_matches = "na")
#> Joining, by = c("A", "D")
#> # Source: lazy query [?? x 4]
#> # Database: sqlite 3.29.0 [:memory:]
#> A B D C
#> <chr> <chr> <chr> <chr>
#> 1 a b d c
inner_join(df_1, df_2, na_matches = "na")
#> Joining, by = c("A", "D")
#> # A tibble: 2 x 4
#> A B D C
#> <chr> <chr> <chr> <chr>
#> 1 a b d c
#> 2 aa bb <NA> cc

最佳答案

为了响应@philipxy 在left_join 过程中进一步挖掘的请求,我进入了left_join 的 Debug模式。 ,首先在数据表上:

debug(left_join)
left_join(dt_1, dt_2, na_matches = "na")
#> debugging in: left_join(dt_1, dt_2, na_matches = "na")
#> debug: {
#> UseMethod("left_join")
#> }
Browse[2]> n
#> debug: UseMethod("left_join")
#> Browse[2]> n
#> debugging in: left_join.tbl_lazy(dt_1, dt_2, na_matches = "na")
#> debug: {
#> add_op_join(x, y, "left", by = by, sql_on = sql_on, copy = copy,
#> suffix = suffix, auto_index = auto_index, ...)
#> }
Browse[3]>
#> debug: add_op_join(x, y, "left", by = by, sql_on = sql_on, copy = copy,
#> suffix = suffix, auto_index = auto_index, ...)
Browse[3]> s
#> debugging in: add_op_join(x, y, "left", by = by, sql_on = sql_on, copy = copy,
#> suffix = suffix, auto_index = auto_index, ...)
#> debug: {
#> if (!is.null(sql_on)) {
#> by <- list(x = character(0), y = character(0), on = sql(sql_on))
#> }
#> else if (identical(type, "full") && identical(by, character())) {
#> type <- "cross"
#> by <- list(x = character(0), y = character(0))
#> }
#> else {
#> by <- common_by(by, x, y)
#> }
#> y <- auto_copy(x, y, copy = copy, indexes = if (auto_index)
#> list(by$y))
#> vars <- join_vars(op_vars(x), op_vars(y), type = type, by = by,
#> suffix = suffix)
#> x$ops <- op_double("join", x, y, args = list(vars = vars,
#> type = type, by = by, suffix = suffix))
#> x
#> }
Browse[4]> f
#> Joining, by = c("A", "D")
#> exiting from: add_op_join(x, y, "left", by = by, sql_on = sql_on, copy = copy,
#> suffix = suffix, auto_index = auto_index, ...)
#> exiting from: left_join.tbl_lazy(dt_1, dt_2, na_matches = "na")
#> exiting from: left_join(dt_1, dt_2, na_matches = "na")
#> # Source: lazy query [?? x 4]
#> # Database: sqlite 3.29.0 [:memory:]
#> A B D C
#> <chr> <chr> <chr> <chr>
#> 1 a b d c
#> 2 aa bb NA NA

我们看到 left_join来电 left_join.tbl_lazy在带有 na_matches = “na” 的数据表上选项。
然而,这之后是对 add_op_join 的调用。其定义未提及 na_matches .

然后,相比之下,在数据帧上:
left_join(df_1, df_2)
#> debugging in: left_join(df_1, df_2)
#> debug: {
#> UseMethod("left_join")
#> }
Browse[2]> n
#> debug: UseMethod("left_join")
Browse[2]>
#> debugging in: left_join.tbl_df(df_1, df_2)
#> debug: {
#> check_valid_names(tbl_vars(x))
#> check_valid_names(tbl_vars(y))
#> by <- common_by(by, x, y)
#> suffix <- check_suffix(suffix)
#> na_matches <- check_na_matches(na_matches)
#> y <- auto_copy(x, y, copy = copy)
#> vars <- join_vars(tbl_vars(x), tbl_vars(y), by, suffix)
#> by_x <- vars$idx$x$by
#> by_y <- vars$idx$y$by
#> aux_x <- vars$idx$x$aux
#> aux_y <- vars$idx$y$aux
#> out <- left_join_impl(x, y, by_x, by_y, aux_x, aux_y, na_matches,
#> environment())
#> names(out) <- vars$alias
#> reconstruct_join(out, x, vars)
#> }
Browse[3]>
#> debug: check_valid_names(tbl_vars(x))
Browse[3]>
#> debug: check_valid_names(tbl_vars(y))
Browse[3]>
#> debug: by <- common_by(by, x, y)
Browse[3]>
#> Joining, by = c("A", "D")
#> debug: suffix <- check_suffix(suffix)
Browse[3]>
#> debug: na_matches <- check_na_matches(na_matches)
Browse[3]>
#> debug: y <- auto_copy(x, y, copy = copy)
Browse[3]> na_matches
#> [1] TRUE
Browse[3]> f
#> exiting from: left_join.tbl_df(df_1, df_2)
#> exiting from: left_join(df_1, df_2)
#> # A tibble: 2 x 4
#> A B D C
#> <chr> <chr> <chr> <chr>
#> 1 a b d c
#> 2 aa bb NA cc

我们看到 left_join来电 left_join.tbl_df在数据帧上。再往下,我们看到 na_matches设置为 TRUE在用作 left_join_impl 中的参数之前.这一切都是有道理的。

输入 ?left_join.tbl_lazy 时文档返回 join.tbl_sql {dbplyr} 的本地页面其中声明了未指定的参数( ):

“传递给方法的其他参数,例如, na_matches 控制 NA 值的匹配方式。见 join.tbl_df更多”。

关注 join.tbl_df文档链接,它清楚地提到了 na_matches :

“使用 'never' 始终将两个 NA 或 NaN 值视为不同,例如数据库源的连接,类似于 merge(incomparables = FALSE)。默认值 'na' 始终将两个 NA 或 NaN 值视为相等,例如合并(). 用户和包作者可以通过调用 pkgconfig::set_config('dplyr::na_matches' = 'never')"来更改默认行为。

所以文档和数据表的代码之间似乎存在一些不一致。

此外,@philipxy 提到了这个 news link其中声明“要匹配 NA 值,请将 na_matches = 'na' 传递给连接动词; 仅支持数据帧 ”。现在 dt_1 和 df_1 的类是:
class(df_1)
#> [1] "tbl_df" "tbl" "data.frame"
class(dt_1)
#> [1] "tbl_SQLiteConnection" "tbl_dbi" "tbl_sql"
#> [4] "tbl_lazy" "tbl"

我想术语“数据框”是指类 data.frametbl_df ,而我所说的“数据表”是另一个 tbl_*包括 tbl_sqltbl_lazy .所以这个新闻链接也回答了这个问题。

不过,我认为连接动词的当前文档令人困惑。它应该清楚地说明:

对于数据框默认为 na_matches = 'na',对于数据表 默认为 na_matches = 'never'(没有其他选择)”。

希望,选择 na_matches = "na"数据表将在不久的将来实现。

关于r - left_join 用于 tbl : na_matches not working,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57734832/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com