求助:使用Tidyverse及基础R实现宽表转长表的两种方法
我来帮你搞定宽格式转长格式的需求,同时修复你使用基础Rreshape()函数时碰到的错误。下面分别给出两种实现方案:
方法一:使用Tidyverse的
pivot_longer() 这是tidyverse生态里最直观的宽转长工具,代码简洁易读:
# 先加载tidyverse包 library(tidyverse) # 定义原始数据框 df2 <- data.frame(name = c("John", "Anna", "Jonte"), Matematyka = c(2, 3, 5), Polski = c(5, 5, 4)) # 宽转长并替换科目名称 df_long_tidy <- df2 %>% pivot_longer(cols = -name, # 选中除name外的所有列作为要转换的列 names_to = "subject", # 原列名存入subject列 values_to = "mark") %>% # 原列值存入mark列 mutate(subject = recode(subject, # 替换科目名称为你期望的英文 Matematyka = "math", Polski = "eng")) # 查看结果 print(df_long_tidy)
运行后会得到你想要的结果:
# A tibble: 6 × 3 name subject mark <chr> <chr> <dbl> 1 John math 2 2 John eng 5 3 Anna math 3 4 Anna eng 5 5 Jonte math 5 6 Jonte eng 4
方法二:基础R的
reshape()函数(修复你的错误) 你之前的错误出在**v.names参数不能传列表**,而且没有指定timevar和times来定义转换后的科目名称。正确的用法如下:
# 定义原始数据框 df2 <- data.frame(name = c("John", "Anna", "Jonte"), Matematyka = c(2, 3, 5), Polski = c(5, 5, 4)) # 正确使用reshape()宽转长 df_long_base <- reshape(df2, direction = "long", varying = 2:3, # 指定要转换的列(第2到第3列) v.names = "mark", # 存储数值的列名(单个字符串,不是列表) idvar = "name", # 分组的标识列 timevar = "subject", # 存储原列名的新列名 times = c("math", "eng"), # 替换原列名的自定义科目名称 new.row.names = 1:6) # 重置行号 # 调整列顺序(和你期望的结果一致) df_long_base <- df_long_base[, c("name", "subject", "mark")] # 查看结果 print(df_long_base)
运行后输出:
name subject mark 1 John math 2 2 Anna math 3 3 Jonte math 5 4 John eng 5 5 Anna eng 5 6 Jonte eng 4
错误原因解释
你之前的代码里v.names = list("subject","mark")是错误的:reshape()中v.names是用来指定数值列的名称,而原列名的存储是通过timevar和times来控制的,不需要把subject放在v.names里,这才导致了invalid 'type' (list) of argument的错误。
内容的提问来源于stack exchange,提问作者Potato
相关产品推荐
相关产品推荐

