R语言rbind合并数据框报row.names重复错误及宽表转长表实现
报错原因
rbind()拼接数据框时强制要求行名唯一,你逐次循环取单年份子集时,每个子集都会继承原total_authority表的行号:如果原表有10行,不管取1994还是1995年的子集,行名都是1-10。第一次拼接1994年数据到空数据框不会触发问题,第二次拼接1995年数据时,两份子集行名完全重复,就会抛出你看到的重复行名错误,警告信息里列的1到10就是重复的行名值。
最优实现方案(无需编写循环)
这种多组列匹配的宽转长场景不需要写for循环,直接用tidyverse的宽转长函数一步完成即可,代码简洁不容易出错:
# 加载tidyverse包,未安装的话先运行install.packages("tidyverse") library(tidyverse) final_output <- total_authority %>% pivot_longer( cols = everything(), names_to = c(".value", "year"), # 按列名规则匹配国家列、得分列,按后缀区分年份 names_pattern = "(country|score)\\.?([0-9]*)", values_drop_na = TRUE ) %>% mutate( # 把列后缀替换为实际年份值:无后缀对应1994,后缀.1对应1995 year = case_when( year == "" ~ "1994", year == "1" ~ "1995" ), score = as.numeric(score) ) %>% # 按要求调整列顺序:国家名称、年份、指标得分 select(country, year, score)
运行前注意两个细节:
- 如果原表1994、1995年的得分列名不是
score/score.1,只需要修改names_pattern参数里的正则,匹配你自己的得分列名即可。比如得分列叫auth_score/auth_score.1,就把正则改成"(country|auth_score)\\.?([0-9]*)" - 如果某一年存在缺失的国家/得分记录,
values_drop_na = TRUE会自动丢弃无效行,不需要额外做缺失值过滤。
原有循环逻辑修复方案
如果要沿用你原来逐个子集拼接的思路,只需要在构建单年份子集时加上row.names = NULL参数重置行名,就能避开重复行名报错,示例代码如下:
# 初始化空结果表 final_output <- data.frame() # 拼接1994年数据 df_1994 <- data.frame( country = total_authority$country, year = "1994", score = total_authority$`替换为你的1994年得分列名`, row.names = NULL # 核心:重置行名,避免重复 ) final_output <- rbind(final_output, df_1994) # 拼接1995年数据 df_1995 <- data.frame( country = total_authority$country.1, year = "1995", score = total_authority$`替换为你的1995年得分列名`, row.names = NULL # 核心:重置行名,避免重复 ) final_output <- rbind(final_output, df_1995)
提示:只有两年数据的场景完全不需要写for循环,直接构建两个单年份子集拼接即可,循环逻辑反而会增加不必要的代码复杂度。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

