使用Base R的reshape函数转换数据框为长格式时遇报错求助
Base R宽表转长表报错解决方案
问题背景
现有一个宽格式数据集,包含1列产品描述(Product)和3列年份数值列(1996、2007、2020),需要转换为包含Product、Year、Value三列的长格式。
数据集结构
croatia_yield <- structure(list(Product = c("Soft wheat", "Durum wheat", "Rye", "Barley", "Oat", "Maize", "Sorghum", "Triticale", "Other cereals", "Total cereals"), `1996` = c(3.6616684588, NA, 2.64103083700441, 2.814404478, 2.399888609, 5.1972385322, NA, NA, 3.4615, 4.36583009052598 ), `2007` = c(5.21289336717319, 4.8786599019381, 2.46478612716763, 3.78568144067797, 1.98542545584555, 4.91636347253509, NA, 3.45350553505535, 2.73019718309859, 4.7024162704803), `2020` = c(5.76343534131085, 4.17933552631579, 4.03194339622642, 4.80996336499322, 3.33150257731959, 8.39248085991678, NA, 4.16039316239316, 1.72273076923077, 6.92400090523919 )), row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"))
尝试的代码及报错
执行以下reshape代码:
reshape(croatia_yield, direction = "long", varying = c("1996", "2007", "2020"), v.names = "Value", timevar = "Year", times = c("1996", "2007", "2020"), new.row.names = 1:30)
出现报错:
Error in `[<-`: ! Assigned data `ids` must be compatible with existing data. ✖ Existing data has 30 rows. ✖ Assigned data has 10 rows. ℹ Only vectors of size 1 are recycled. Caused by error in `vectbl_recycle_rhs_rows()`: ! Can't recycle input of size 10 to size 30. Run `rlang::last_trace()` to see where the error occurred.
原因分析
报错根源是数据集为tibble(tbl_df)类型,Base R的reshape函数对tibble的兼容性较差:tibble对数据长度匹配的检查更严格,而reshape未自动识别Product作为分组ID列,导致生成的30行长数据与原10行的ID列无法匹配,触发循环回收失败。
解决方案(仅Base R)
方案1:转换为普通DataFrame后再处理
将tibble转换为Base R原生的data.frame,消除类型限制:
# 转换为普通data.frame croatia_yield_df <- as.data.frame(croatia_yield) # 执行宽转长 long_data <- reshape(croatia_yield_df, direction = "long", varying = c("1996", "2007", "2020"), v.names = "Value", timevar = "Year", times = c("1996", "2007", "2020"), new.row.names = 1:30)
方案2:显式指定分组ID列
在reshape中通过idvar参数明确指定Product作为分组列,让函数正确识别数据分组逻辑:
long_data <- reshape(croatia_yield, direction = "long", varying = c("1996", "2007", "2020"), v.names = "Value", timevar = "Year", times = c("1996", "2007", "2020"), idvar = "Product", # 显式指定分组列 new.row.names = 1:30)
两种方案都能得到预期的长格式数据,包含Product、Year和Value三列。
内容的提问来源于stack exchange,提问作者Rafael Gomes
相关产品推荐
相关产品推荐

