You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在R中将多年份列宽格式数据转长格式及UTF-8问题排查

宽格式转长格式解决方案(含编码与空格列处理)

我有一份宽格式数据,包含10个年份列、19类带年份后缀的连续数据列,以及ID和分类列,需要转换为单一年份列的长格式。尝试过plyr、reshape、melt等方法均未成功,同时遇到UTF-8编码问题,持续报错“Error unexpected symbol”。部分类别名称含空格(如“Sum eiendeler”),怀疑与plyr兼容性有关。以下是数据示例的dput子集:

dput(head(subset, encoding="UTF-8"))
structure(list(Kommunenr = c(3024, 3003, 3026, 3024, 3005, 3024
), Kommunenavn = c("B�†RUM", "SARPSBORG", "AURSKOG-H�˜LAND", 
"B�†RUM", "DRAMMEN", "B�†RUM"), Poststed = c("LYSAKER", 
"SARPSBORG", "AURSKOG", "OSLO", "DRAMMEN", "LYSAKER"), Firmanavn = c("SIBELCO NORDIC AS", 
"BORREGAARD AS", "RENOR AS", "IBKA NORGE AS", "LINDUM AS", "ABB AS"), Omsetning = c(1120829, 4560381, 165102, 95528, 534988, 4831283
), `Omsetning (-1 år)` = c(970373, 4109890, 164965, 95592, 590392, 
4447881), `Omsetning (-2 år)` = c(1042016, 3833545, 152611, 
134110, 571098, 4913517), `Omsetning (-3 år)` = c(1139725, 3632657, 
156393, 126319, 503298, 8528459), `Omsetning (-4 år)` = c(1101891, 
3494357, 139160, 127351, 501145, 8629261), `Omsetning (-5 år)` = c(1018331, 
3354595, 128425, 328448, 467739, 9062316), `Omsetning (-6 år)` = c(967473, 
3032051, 128607, 480547, 364653, 9281909), `Omsetning (-7 år)` = c(925051, 
3001124, 137716, 587045, 321790, 11213573), `Omsetning (-8 år)` = c(817706, 
3076555, 135565, 620426, 281758, 11363403), `Omsetning (-9 år)` = c(869521, 
3001972, 143661, 506029, 258282, 9596080), `Lønnskostnader` = c(222248, 
801995, 45854, 44275, 134000, 1638857), `Ordinært resultat` = c(75771, 
625441, 4405, -4518, 20387, 210731), `Ordinært resultat (-1 år)` = c(102996, 
382166, 4020, 1735, 47294, 34840), `Ordinært resultat (-2 år)` = c(129144, 
375137, 3896, -4458, 30535, 134473), `Ordinært resultat (-3 år)` = c(89943, 
468869, 5320, 24016, 35222, 304241), `Ordinært resultat (-4 år)` = c(153231, 
509385, 714, -5844, 46260, 298099), `Ordinært resultat (-5 år)` = c(160850, 
512248, -6328, 64602, 28472, 315443), `Ordinært resultat (-6 år)` = c(154387, 
247849, -7225, -7176, 23329, 564357), `Ordinært resultat (-7 år)` = c(102746, 
212834, -4144, -7117, 23103, 649626), `Ordinært resultat (-8 år)` = c(43573, 
143042, -1720, 2221, 42606, 544287), `Ordinært resultat (-9 år)` = c(55495, 
242609, 3700, -2504, 29300, 620666), Goodwill = c(0, 0, 0, 0, 
0, 1124), `Goodwill (-1 år)` = c(0, 0, 0, 0, 0, 2188), `Goodwill (-2 år)` = c(0, 
0, 0, 0, 0, 6963), `Goodwill (-3 år)` = c(131834, 0, 0, 0, 0, 
12790), `Goodwill (-4 år)` = c(134854, 0, 0, 360, 0, 26327), 
    `Goodwill (-5 år)` = c(138229, 0, 0, 0, 0, 39247), `Goodwill (-6 år)` = c(141427, 
    0, 0, 20613, 0, 47812), `Goodwill (-7 år)` = c(144031, 0, 
    0, 23027, 497, 0), `Goodwill (-8 år)` = c(146560, 0, 0, 
    25713, 0, 0), `Goodwill (-9 år)` = c(149051, 0, 0, 36596, 
    0, 77302), Orgnr = c(965724737, 895623032, 935906865, 952070533, 
    979618840, 982085160), `Regnskapsår` = c(2021, 2021, 2021, 
    2021, 2021, 2021), `Regnskapsår (-1 år)` = c(2020, 2020, 
    2020, 2020, 2020, 2020), `Regnskapsår (-2 år)` = c(2019, 
    2019, 2019, 2019, 2019, 2019), `Regnskapsår (-3 år)` = c(2018, 
    2018, 2018, 2018, 2018, 2018), `Regnskapsår (-4 år)` = c(2017, 
    2017, 2017, 2017, 2017, 2017), `Regnskapsår (-5 år)` = c(2016, 
    2016, 2016, 2016, 2016, 2016), `Regnskapsår (-6 år)` = c(2015, 
    2015, 2015, 2015, 2015, 2015), `Regnskapsår (-7 år)` = c(2014, 
    2014, 2014, 2014, 2014, 2014), `Regnskapsår (-8 år)` = c(2013, 
    2013, 2013, 2013, 2013, 2013), `Regnskapsår (-9 år)` = c(2012, 
    2012, 2012, 2012, 2012, 2012)), row.names = c(NA, -6L), class = c("tbl_df", 
"tbl", "data.frame"))

一、编码问题预处理

先解决UTF-8编码异常,确保字符列显示正常:

library(tidyverse)

# 针对dput导入的数据,统一转换字符列为UTF-8编码
df <- structure(...) # 替换为你的dput内容
df <- df %>% mutate(across(where(is.character), ~iconv(., from = "latin1", to = "UTF-8")))

二、用pivot_longer实现宽转长

tidyverse的pivot_longer对含空格、特殊字符的列名兼容性更强,无需担心plyr的适配问题:

long_df <- df %>%
  pivot_longer(
    cols = -c(Kommunenr, Kommunenavn, Poststed, Firmanavn, Orgnr), # 保留不需要转换的ID/分类列
    names_to = c("指标类型", "年份偏移"),
    # 正则匹配列名,拆分指标类型和年份后缀
    names_pattern = "(.*?)(?: \\((-\\d+ år)\\))?$",
    values_to = "指标值"
  ) %>%
  # 计算实际年份
  mutate(
    年份偏移 = replace_na(年份偏移, "0 år"),
    年份偏移数值 = as.integer(str_extract(年份偏移, "-?\\d+")),
    实际年份 = `Regnskapsår` + 年份偏移数值
  ) %>%
  # 整理列顺序,移除冗余列
  select(Kommunenr, Kommunenavn, Poststed, Firmanavn, Orgnr, 实际年份, 指标类型, 指标值)

正则说明

(.*?)(?: \\((-\\d+ år)\\))?$:

  • (.*?):非贪婪匹配指标名称(如Omsetning、Ordinært resultat)
  • (?: \\((-\\d+ år)\\))?$:可选匹配年份后缀(如(-1 år)),并提取偏移数值

三、验证结果

查看转换后的前几行数据:

head(long_df)

额外问题处理

如果仍有编码异常,用stringi包强制转换:

library(stringi)
df <- df %>% mutate(across(where(is.character), stri_enc_toutf8))

内容的提问来源于stack exchange,提问作者SarpsRosing

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 07:25:20