R语言将含数百个月份列的宽数据集转换为长格式
R语言宽表转长表实现方案(适配多月份列场景)
问题背景
- 现有存储YouTube频道数据的宽表:包含频道名称
Channel_title、3类受众标签列,以及数百个按YYYY-MM格式命名的月度浏览量列。 - 转换目标:保留频道名称、受众标签列,将所有月度浏览量列拆分为
Month(月份)、Views_for_that_month(当月浏览量)两个字段,输出标准长格式表。 - 原有尝试代码:
long <- melt(setDT(DF), id.vars = colnames(DF), variable.name = "Channel_title")无法得到预期结果。
原代码错误原因
id.vars参数传入了全部列名,意味着没有指定需要拉长的度量列,转换逻辑不成立。variable.name错误映射为已存在的Channel_title字段,列名匹配逻辑完全错误。
可直接复用的实现代码
两种方案均自动识别所有符合年月命名规则的列,无需手动枚举数百个月份列,可直接适配你的实际数据场景。
方案1:tidyverse 方案(语法直观,适合常规数据量)
library(tidyverse) long_df <- DF %>% pivot_longer( cols = matches("^\\d{4}-\\d{2}$"), # 自动匹配所有YYYY-MM格式的月份列 names_to = "Month", values_to = "Views_for_that_month" ) %>% # 以下为匹配目标结构的可选操作 mutate( # 将字符串格式的TRUE/FALSE转为逻辑型 across(c(Kids_13_and_under, `Teens_13-17`, Adults_17_and_older), as.logical) ) %>% # 重命名列匹配目标格式 rename(Teens_13_17 = `Teens_13-17`)
方案2:data.table 方案(性能优异,适合百万行以上大数据量)
library(data.table) setDT(DF) # 自动识别所有月份列 month_cols <- grep("^\\d{4}-\\d{2}$", colnames(DF), value = TRUE) long_dt <- melt( DF, id.vars = setdiff(colnames(DF), month_cols), # 非月份列全部保留为标识列 measure.vars = month_cols, variable.name = "Month", value.name = "Views_for_that_month" ) # 以下为匹配目标结构的可选操作 long_dt[, c("Kids_13_and_under", "Teens_13-17", "Adults_17_and_older") := lapply(.SD, as.logical), .SDcols = c("Kids_13_and_under", "Teens_13-17", "Adults_17_and_older")] setnames(long_dt, "Teens_13-17", "Teens_13_17")
输出效果
运行代码后得到的长表完全匹配目标结构:每个频道对应每个月一行数据,频道属性列自动复用填充,月度浏览量和月份一一对应。
内容的提问来源于stack exchange,提问作者firmo23
相关产品推荐
相关产品推荐

