如何在pivot_longer中为names_sep/names_pattern传入多分隔规则?
解决方案
你可以通过tidyr包的pivot_longer配合正则表达式风格的names_pattern参数,一次性拆分所有列名中的issue、country、party字段,再按需整理成目标格式,无需逐个国家处理。
步骤1:加载依赖包
library(tidyr) library(dplyr)
步骤2:批量转换格式
假设你的原始数据框为df,其中expert是每行的唯一标识列,其余列均为issue_country_party格式(如immigration_au_spo):
情况1:生成纯长格式(每行对应expert-country-party-issue-数值)
如果需要的是最基础的长格式结构,只需要一次pivot_longer操作:
df_long_basic <- df %>% pivot_longer( cols = -expert, # 排除标识列expert names_to = c("issue", "country", "party"), # 正则匹配:任意字符(issue)_任意非下划线字符(country)_任意字符(party) names_pattern = "(.*)_([^_]+)_(.*)" )
情况2:生成包含expert、country、party及各类issue列的结构
如果需要把issue转为单独的列(如immigration、leftright作为列名),在第一步基础上追加pivot_wider即可:
df_final <- df %>% pivot_longer( cols = -expert, names_to = c("issue", "country", "party"), names_pattern = "(.*)_([^_]+)_(.*)" ) %>% pivot_wider( id_cols = c(expert, country, party), names_from = issue, values_from = value )
关键说明
names_pattern的正则逻辑:(.*)匹配任意长度字符(对应issue和party),([^_]+)匹配两个下划线之间的所有非下划线字符(对应country代码),确保兼容不同长度的国家代码(两位或三位)。- 如果你的国家代码是固定两位(如
au、nl),可以把正则改为"(.*)_(..)_(.*)",匹配更精准。 - 若数据中存在非目标格式的列,可通过
cols参数明确指定要处理的列,比如cols = matches(".*_.*_.*")(匹配包含两个下划线的列)或cols = starts_with(c("immigration", "leftright"))。
内容的提问来源于stack exchange,提问作者Andrej
相关产品推荐
相关产品推荐

