使用原始表名称为 left_join() 生成的所有列添加前缀

Posted

技术标签:

【中文标题】使用原始表名称为 left_join() 生成的所有列添加前缀【英文标题】:Prefix all columns resulting from left_join() with original table names 【发布时间】:2016-10-24 20:01:17 【问题描述】:

我想为左连接产生的所有列添加前缀。

left_join() 可以在连接的两个表之间的名称相同时添加后缀。但是,即使它们的名称不同,它也没有始终添加此后缀的选项。而且它没有添加前缀的选项。

library(dplyr)
library(nycflights13)
flights2 <- flights %>% select(year:day, hour, origin, dest, tailnum, carrier)
airports2 <- airports

result <- flights2 %>% left_join(airports2, c("dest" = "faa")) %>% head()

结果:

Source: local data frame [6 x 14]

year month   day  hour origin  dest tailnum carrier                            name
(int) (int) (int) (dbl)  (chr) (chr)   (chr)   (chr)                           (chr)
1  2013     1     1     5    EWR   IAH  N14228      UA    George Bush Intercontinental
2  2013     1     1     5    LGA   IAH  N24211      UA    George Bush Intercontinental
3  2013     1     1     5    JFK   MIA  N619AA      AA                      Miami Intl
4  2013     1     1     5    JFK   BQN  N804JB      B6                              NA
5  2013     1     1     5    LGA   ATL  N668DN      DL Hartsfield Jackson Atlanta Intl
6  2013     1     1     5    EWR   ORD  N39463      UA              Chicago Ohare Intl
Variables not shown: lat (dbl), lon (dbl), alt (int), tz (dbl), dst (chr)

这里,只能从join结果中无法知道每一列来自哪个原始表。

添加此前缀的目的是为了可靠地根据表名和从关系数据库加载的数据的列名计算列名。例如,将使用加载并存储在R 中的数据库结构和关系数据库的命名约定来识别主键和外键。然后这些将用于设置连接,并在以后从连接结果中检索数据。

我发现mysql 的类似问题,但R 没有:

In a join, how to prefix all column names with the table it came from

【问题讨论】:

【参考方案1】:

实现此目的的一种直接方法是在执行连接之前将前缀添加到原始表中:

# add prefix before joining:
names(flights2) <- paste0("flights2.", names(flights2) )
names(airports2) <- paste0("airports2.", names(airports2) )

# in join, use names with prefixes
result <- flights2 %>% left_join(airports2, c("flights2.dest" = "airports2.faa") ) %>% head()

结果:

Source: local data frame [6 x 14]

flights2.year flights2.month flights2.day flights2.hour flights2.origin flights2.dest
(int)          (int)        (int)         (dbl)           (chr)         (chr)
1          2013              1            1             5             EWR           IAH
2          2013              1            1             5             LGA           IAH
3          2013              1            1             5             JFK           MIA
4          2013              1            1             5             JFK           BQN
5          2013              1            1             5             LGA           ATL
6          2013              1            1             5             EWR           ORD
Variables not shown: flights2.tailnum (chr), flights2.carrier (chr), airports2.name (chr),
airports2.lat (dbl), airports2.lon (dbl), airports2.alt (int), airports2.tz (dbl),
airports2.dst (chr)

现在,可以通过这种方式轻松引用连接的数据框:tableName.columnName

【讨论】:

flights2::year 不是语法上有效的名称。我会使用flights2_flights2. 关系数据库 (FileMaker) 使用此命名约定,因此我想保留这些名称,即使它们不适合 R。我也有以下划线开头的列名。你能举一个例子说明它会在哪里导致问题或需要重新格式化吗?我正在使用[[ 进行索引。 当我们使用 dplyr 时,试试这个例子:mtcars$col1 &lt;- seq(nrow(mtcars)); colnames(mtcars)[12] &lt;- "xx:yy"; mtcars %&gt;% filter(xx::yy &gt; 5) 我可以毫无问题地将:: 切换为.,但如果能进一步了解我为什么要这样做会很好。 好的,我相信了!我现在切换到.。谢谢!【参考方案2】:

类似的答案,但对于后缀和一个流程:

[编辑:从 dplyr 0.8.0 开始,“funs() 的更改已被软弃用”/edit]

library(dplyr)
(band_members
%>% rename_all( list(~paste0(., ".left")))  # < dpylr 0.8.0: %>% rename_all( funs(paste0(., ".left")))
%>% left_join(band_instruments, by = c("name.left"="name"))
%>% rename_at( .vars = vars(-ends_with(".left")),list(~paste0(., ".right")))# < dpylr 0.8.0: %>% rename_at( .vars = vars(-ends_with(".left")),funs(paste0(., ".right"))
)

(band_members
  %>% rename_all( list(~paste0(., ".left")))  # < dpylr 0.8.0: %>% rename_all( funs(paste0(., ".left"))) 
  %>% left_join(
  band_instruments %>% rename_all( list(~paste0(., ".right"))), # < dpylr 0.8.0: band_instruments%>% rename_all( funs(paste0(., ".right")))
  by = c("name.left"="name.right")
  )
)  

两者都给出:

    #  A tibble: 3 x 3
  name.left band.left plays.right
  <chr>     <chr>     <chr>      
1 Mick      Stones    <NA>       
2 John      Beatles   guitar     
3 Paul      Beatles   bass 

编辑:使用来自 dplyr 文档的数据

library(tidyverse)

band_members <- tribble(
  ~ name,    ~ band,
  "Mick",  "Stones",
  "John", "Beatles",
  "Paul", "Beatles"
)

band_instruments <- tribble(
  ~ name,   ~ plays,
  "John",  "guitar",
  "Paul",    "bass",
  "Keith", "guitar"
)

【讨论】:

以上是关于使用原始表名称为 left_join() 生成的所有列添加前缀的主要内容,如果未能解决你的问题,请参考以下文章

dplyr::left_join 是不是等同于 base::merge(..., all.x=TRUE)?

优化 R 中输出表生成的代码

将多行合并为一列,同时用原始表中的“名称”字段替换键

从 Laravel 输出原始 HTML

VBA excel添加新工作表并删除原来的

如何使用jquery访问具有值= xx的所选项目名称的值