R语言:基于正则表达式将单列拆分为多列的问题
拆分DataFrame列表型数值列为独立列
问题场景
现有仅含col_names列的DataFrame,每行内容包含省份名称(如Aceh、Sumatera.Utara)及6个带小数的数值(以大量点分隔),需要转换为包含Province列及Value_1至Value_6共7列的DataFrame。
原DataFrame
| col_names |
|---|
| Aceh..........................................................66.29..........................56.49..........................64.01..................................49.72.....................................39.58...............................52.15 |
| Sumatera.Utara.........................................88.20..........................82.19..........................79.45..................................66.94.....................................53.35...............................73.16 |
| Sumatera.Barat..........................................84.48..........................74.76..........................79.30..................................55.64.....................................44.68...............................78.55 |
目标DataFrame
| Province | Value_1 | Value_2 | Value_3 | Value_4 | Value_5 | Value_6 |
|---|---|---|---|---|---|---|
| Aceh | 66.29 | 56.49 | 64.01 | 49.72 | 39.58 | 52.15 |
| Sumatera.Utara | 88.20 | 82.19 | 79.45 | 66.94 | 53.35 | 73.16 |
| Sumatera.Barat | 84.48 | 74.76 | 79.30 | 55.64 | 44.68 | 78.55 |
现有代码问题
已编写代码提取省份和数值列表,但数值仍处于同一列(列表格式),且原省份提取正则无法匹配不带点的省份(如Aceh):
df$province <- str_extract(df$col_names, '\\w*\\.\\w*') df$values <- str_extract_all(df$col_names, '[0-9]+\\.[0-9]+') df <- subset(df, select = c(province, values))
解决方案
方案1:使用tidyr快速拆分(推荐)
先修正省份提取逻辑,再用unnest_wider直接拆分列表列,最后重命名列名:
library(tidyr) library(stringr) # 提取省份:匹配开头连续非点字符,兼容带点和不带点的省份名 df$Province <- str_extract(df$col_names, '^[^.]+') # 提取数值列表并拆分为多列 df_final <- df %>% mutate(values = str_extract_all(col_names, '[0-9]+\\.[0-9]+')) %>% select(Province, values) %>% unnest_wider(values, names_sep = "_") %>% rename_with(~paste0("Value_", 1:6), starts_with("values_"))
方案2:基础R实现(无需额外包)
用do.call(rbind)把列表转成矩阵,再和省份列合并:
library(stringr) # 修正省份提取 df$Province <- str_extract(df$col_names, '^[^.]+') # 提取数值列表 df$values <- str_extract_all(df$col_names, '[0-9]+\\.[0-9]+') # 列表转矩阵并添加列名 values_matrix <- do.call(rbind, df$values) colnames(values_matrix) <- paste0("Value_", 1:6) # 合并得到最终DataFrame df_final <- cbind(df["Province"], as.data.frame(values_matrix))
完整示例代码
library(tidyr) library(stringr) # 构造示例数据 df <- data.frame( col_names = c( "Aceh..........................................................66.29..........................56.49..........................64.01..................................49.72.....................................39.58...............................52.15", "Sumatera.Utara.........................................88.20..........................82.19..........................79.45..................................66.94.....................................53.35...............................73.16", "Sumatera.Barat..........................................84.48..........................74.76..........................79.30..................................55.64.....................................44.68...............................78.55" ) ) # 执行拆分流程 df$Province <- str_extract(df$col_names, '^[^.]+') df_final <- df %>% mutate(values = str_extract_all(col_names, '[0-9]+\\.[0-9]+')) %>% select(Province, values) %>% unnest_wider(values, names_sep = "_") %>% rename_with(~paste0("Value_", 1:6), starts_with("values_")) # 查看结果 print(df_final)
内容的提问来源于stack exchange,提问作者salmiah-ls
相关产品推荐
相关产品推荐

