如何通过连接操作生成目标长格式数据集?(R语言tidyverse)
如何通过连接操作生成目标长格式数据集?
你想要生成的目标长格式数据集是这样的:
tibble::tribble( ~country, ~fit, ~country_iso, ~year, "Afghanistan", 1.56598484506948, "AFG", "2017", "Angola", -1.68805891716096, "AGO", "2017", "Albania", 0.865738438573542, "ALB", "2017", "Afghanistan", 1.42313952299157, "AFG", "2014", "Angola", -0.889994054489868, "AGO", "2014", "Albania", 0.162782415602255, "ALB", "2014" ) #> # A tibble: 6 x 4 #> country fit country_iso year #> <chr> <dbl> <chr> <chr> #> 1 Afghanistan 1.57 AFG 2017 #> 2 Angola -1.69 AGO 2017 #> 3 Albania 0.866 ALB 2017 #> 4 Afghanistan 1.42 AFG 2014 #> 5 Angola -0.890 AGO 2014 #> 6 Albania 0.163 ALB 2014
而你现有的待连接数据集是这三个:
library(tidyverse) values_2017 <- tibble::tribble( ~country, ~fit, ~year, "Afghanistan", 1.56598484506948, "2017", "Angola", -1.68805891716096, "2017", "Albania", 0.865738438573542, "2017" ) meta <- tibble::tribble( ~country_iso, ~country, "AFG", "Afghanistan", "AGO", "Angola", "ALB", "Albania" ) values_2014 <- tibble::tribble( ~country_iso, ~year, ~fit, "AFG", "2014", 1.42313952299157, "AGO", "2014", -0.889994054489868, "ALB", "2014", 0.162782415602255 )
你之前的问题出在哪?
你之前用full_join或left_join得到宽格式,是因为这类横向连接函数的作用是把同一观测的不同属性合并到同一行里(比如把2017和2014的数据放在同一行的不同列),但你需要的是把2017和2014的记录上下堆叠,也就是纵向合并行,这时候应该用bind_rows(或者基础R的rbind),不过前提是两个数据集的列结构完全一致。
正确的操作步骤
我们需要先把两个年份的数据集都整理成和目标一致的列结构(country, fit, country_iso, year),再纵向合并:
# 处理2017年的数据:连接meta补全country_iso列 values_2017_full <- values_2017 %>% left_join(meta, by = "country") # 处理2014年的数据:连接meta补全country列,同时调整列顺序匹配2017的数据集 values_2014_full <- values_2014 %>% left_join(meta, by = "country_iso") %>% select(country, fit, year, country_iso) # 确保列顺序和前者完全一致 # 纵向合并两个数据集,得到目标长格式 final_data <- bind_rows(values_2017_full, values_2014_full) # 查看结果 final_data
运行后就能得到你想要的输出:
#> # A tibble: 6 x 4 #> country fit country_iso year #> <chr> <dbl> <chr> <chr> #> 1 Afghanistan 1.57 AFG 2017 #> 2 Angola -1.69 AGO 2017 #> 3 Albania 0.866 ALB 2017 #> 4 Afghanistan 1.42 AFG 2014 #> 5 Angola -0.890 AGO 2014 #> 6 Albania 0.163 ALB 2014
更简洁的写法
如果你想少写点代码,可以用purrr的map_dfr来批量处理两个数据集:
list(values_2017, values_2014) %>% map_dfr(function(df) { # 根据数据集的现有列自动匹配连接meta,再调整列顺序 if ("country_iso" %in% colnames(df)) { df %>% left_join(meta, by = "country_iso") } else { df %>% left_join(meta, by = "country") } %>% select(country, fit, year, country_iso) # 统一列顺序 })
核心知识点总结
- 横向连接(
left_join/full_join等):增加列数,用于合并同一观测的不同属性; - 纵向连接(
bind_rows):增加行数,用于合并不同观测的同一属性; - 要生成长格式数据,必须先让待合并的数据集列名、列顺序完全一致,再用纵向合并函数。
内容的提问来源于stack exchange,提问作者Balthasar
相关产品推荐
相关产品推荐

