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

如何用R语言函数(如pivot_longer)将调查宽表转为多类型列整洁长表?

解决家庭调查宽表转长表的问题(支持多数据类型)

你提到的pivot_longer完全可以生成包含不同类型列的tidy dataframe,无需逐个处理问题再合并,只要利用列名的规律批量操作即可。针对你的示例数据,这里提供两种高效实现方法:

方法一:分步处理后合并(直观易读)

这种方法将年龄和语言数据分开转换,再合并结果,能清晰保留各列的数据类型:

library(tidyverse)

# 示例数据
df <- tribble(
  ~ID, ~Age_1, ~Age_2, ~Age_3, ~Lang_1_1, ~Lang_1_2, ~Lang_2_1, ~Lang_2_2, ~Lang_3_1, ~Lang_3_2,
  1, 20, 25, 30, "English", NA, "English", NA, "English", "French",
  2, 21, 25, 47, "English", "French", "English", NA, "English", "French",
  3, 17, 42, 43, NA, "French", NA, "French", NA, "French"
)

# 1. 转换年龄列到长格式
age_long <- df %>%
  select(ID, starts_with("Age")) %>%
  pivot_longer(
    cols = starts_with("Age"),
    names_to = "family_member",
    values_to = "Age",
    names_prefix = "Age_"  # 去掉列名中的"Age_"前缀,提取家庭成员编号
  ) %>%
  mutate(family_member = as.integer(family_member))  # 转成整数类型

# 2. 转换语言列到长格式,再转宽为多语言列
lang_long <- df %>%
  select(ID, starts_with("Lang")) %>%
  pivot_longer(
    cols = starts_with("Lang"),
    names_to = c("family_member", "lang_index"),
    values_to = "Language",
    names_pattern = "Lang_(\\d)_(\\d)"  # 用正则拆分列名,提取成员编号和语言序号
  ) %>%
  mutate(family_member = as.integer(family_member)) %>%
  pivot_wider(
    id_cols = c(ID, family_member),
    names_from = lang_index,
    values_from = Language,
    names_prefix = "Lang_"  # 添加前缀生成Lang_1、Lang_2列
  )

# 3. 合并年龄和语言数据
df_final <- age_long %>%
  inner_join(lang_long, by = c("ID", "family_member"))

方法二:一次性转换(更简洁)

通过separate拆分列名,再用pivot_wider整理,一步到位:

df_final <- df %>%
  pivot_longer(cols = -ID, names_to = "name", values_to = "value") %>%
  # 拆分列名为变量类型、成员编号、语言序号(Age列自动补全NA)
  separate(name, into = c("variable", "family_member", "lang_index"), sep = "_", fill = "right") %>%
  pivot_wider(
    id_cols = c(ID, family_member),
    names_from = c(variable, lang_index),
    values_from = value,
    # 生成规范列名:Age、Lang_1、Lang_2
    names_glue = "{variable}{ifelse(is.na(lang_index), '', paste0('_', lang_index))}"
  ) %>%
  # 修正数据类型
  mutate(
    family_member = as.integer(family_member),
    Age = as.numeric(Age)
  )

结果说明

最终生成的df_final每行对应一位家庭成员,包含以下列:

  • ID:访谈编号
  • family_member:家庭成员编号(1/2/3)
  • Age:数值型的年龄数据
  • Lang_1、Lang_2:字符型的语言能力数据

两种方法都能高效处理大量列,只要你的列名遵循Age_成员编号、Lang_成员编号_语言序号的规律,无需手动逐个处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 02:27:45