如何合并这两个数据框?

3
使用R和dplyr:
library(dplyr)

tab1 <- tribble(
  ~code, ~periode, ~prix,
  "a", "2023-01-01", 3,
  "b", "2023-01-01", 2,
  "c", "2023-02-01", 2,
  "d", "2023-02-01", 4
)

tab2 <- tribble(
  ~code, ~`2018-01-01`,  ~`2018-02-01`,  ~`2019-01-01`, ~`2019-02-01`, ~`2020-01-01`,  
  ~`2020-02-01`,~`2021-01-01`,  ~`2021-02-01`, ~`2022-01-01`, ~`2022-02-01`,
  "a", 2, 1, 2, 3, 3, 4, 1, 2, 2, 1,
  "b", 1, 2, 4, 2, 1, 2, 1, 5, 1, 2,
  "c", 2, 1, 5, 6, 1, 3, 4, 3, 1, 3,
  "d", 3, 2, 7, 8, 6, 4, 5, 9, 7, 8
)

我想在tab1中添加三列N_1、N_2和N_3,例如,当tab1中的periode为2023-01-01时:
- N_1包含tab2中2022-01-01的值 - N_2包含tab2中2021-01-01的值 - N_3包含tab2中2020-01-01的值
以下是一个最小可复现示例及预期结果:
# A tibble: 4 × 6
  code  periode     prix   N_1   N_2   N_3
  <chr> <chr>      <dbl> <dbl> <dbl> <dbl>
1 a     2023-01-01     3     2     1     3
2 b     2023-01-01     2     1     1     1
3 c     2023-02-01     2     3     3     3
4 d     2023-02-01     4     8     9     4

在实际表格中,当然会包含每年的所有月份,这就是为什么找到正确的列进行相加非常重要。
我尝试了类似这样的方法:
result <- tab1 |>
 group_by(periode) |> 
 mutate(N_1 = tab2[[""]]... 

非常感谢您的提前帮助!

1
使用left_join(tab1, tab2)基本上可以达到你的目的。你只需要使用rename()函数来重命名列,并且如果有必要的话,重新排列它们,因为tab2中的列顺序与你期望的结果相反。 - undefined
这并不是那么简单,因为根据日期的不同,需要保留并重新命名相同的列。 - undefined
@Seth,请看一下我编辑过的问题。 - undefined
2个回答

2
看起来你想做的是将tab2转换为长格式,筛选出2020年至2022年的数据,将它们重命名为N_1至N_3,然后再将其转换回宽格式,并按月份进行分组。
library(tidyverse)
library(lubridate)
tab2 %>% 
  pivot_longer(-code,names_to = "date") %>%
  mutate(year = year(date),
         month = month(date)) %>%
  filter(year %in% (2020:2022)) %>% 
  select(-date) %>%
  mutate(year = recode(year, `2022` = "N_1", `2021` = "N_2", `2020` = "N_3")) %>%
  pivot_wider(id_cols = c("month","code"),names_from = "year") -> tab2_revised

tab2_revised
## A tibble: 8 × 5
#  month code    N_3   N_2   N_1
#  <dbl> <chr> <dbl> <dbl> <dbl>
#1     1 a         3     1     2
#2     2 a         4     2     1
#3     1 b         1     1     1
#4     2 b         2     5     2
#5     1 c         1     4     1
#6     2 c         3     3     3
#7     1 d         6     5     7
#8     2 d         4     9     8

一旦我们拥有这个,我们就可以按月份与tab1连接。
tab1 %>%
  mutate(month = month(ymd(periode))) %>%
  left_join(tab2_revised, by = c("code","month")) %>%
  select(code,periode,prix,N_1,N_2,N_3)
## A tibble: 4 × 6
#  code  periode     prix   N_1   N_2   N_3
#  <chr> <chr>      <dbl> <dbl> <dbl> <dbl>
#1 a     2023-01-01     3     2     1     3
#2 b     2023-01-01     2     1     1     1
#3 c     2023-02-01     2     3     3     3
#4 d     2023-02-01     4     8     9     4

我觉得我只需要改变filter(year %in% (2020:2022))这一部分,因为当我们到2024年时,这部分会有所变化。非常感谢! - undefined
你会如何从tab1中的2023年信息中进行这个操作? - undefined
嗯,你可以直接使用 cur_year = max(year(tab1$periode)) 作为当前年份,然后不需要硬编码 2020:2022,你可以使用 (cur_year-3):(cur_year-1) - undefined

1
另一个具有动态日期的解决方案。关键是使用seq.Date生成当前日期之前1、2和3年的日期:
library(tidyr)

df2 <- tab2 %>%
  pivot_longer(-1) %>%
  mutate(name=as.Date(name))

tab1 %>%
  mutate(periode2=purrr::map(as.Date(periode),seq,by="-1 year",length.out=4))%>%
  unnest(periode2) %>%
  left_join(df2,join_by(code,closest(periode2>=name))) %>%
  mutate(id=row_number()-1,.by=code) %>%
  filter(id!=0)%>%
  select(-name,-periode2)%>%
  pivot_wider(names_from=id,names_prefix = "N_")

# A tibble: 4 × 6
  code  periode     prix   N_1   N_2   N_3
  <chr> <chr>      <dbl> <dbl> <dbl> <dbl>
1 a     2023-01-01     3     2     1     3
2 b     2023-01-01     2     1     1     1
3 c     2023-02-01     2     3     3     3
4 d     2023-02-01     4     8     9     4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接