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

如何重塑R DataFrame:将单行拆分为两行并迁移选项数据

如何将R中的选择实验宽数据重塑为长数据

这是个很常见的选择实验数据格式转换需求,我来给你分享两种实用的实现方法——用tidyverse工具包会非常简洁高效,偏好base R的话也能轻松搞定:

首先先把你提供的原始数据加载到R里:

# 原始输入数据
df <- structure(list(choice = structure(c(1L, 1L, 2L, 1L), .Label = c("option1", "option2"), class = "factor"), 
                     option1var1 = structure(c(1L, 1L, 1L, 1L), .Label = "A", class = "factor"), 
                     option1var2 = structure(c(1L, 1L, 1L, 2L), .Label = c("B", "H"), class = "factor"), 
                     option2var1 = structure(c(1L, 1L, 2L, 3L), .Label = c("C", "F", "I"), class = "factor"), 
                     option2var2 = structure(1:4, .Label = c("D", "E", "G", "K"), class = "factor")), 
                .Names = c("choice", "option1var1", "option1var2", "option2var1", "option2var2"), 
                class = "data.frame", row.names = c(NA, -4L))

方法一:用tidyverse(推荐)

tidyverse里的dplyr和tidyr组合是处理这类数据重塑的利器,代码简洁易懂:

library(tidyverse)

long_df <- df %>%
  # 先给每个受访者生成唯一ID(用行号就行)
  mutate(respondent = row_number()) %>%
  # 核心步骤:把宽格式的option列转成长格式,同时拆分变量名
  pivot_longer(
    cols = starts_with("option"),  # 选中所有以option开头的列
    names_to = c("option", ".value"),  # 列名拆成两部分:option名称 + 属性变量名
    names_pattern = "(option\\d)(var\\d)"  # 正则表达式匹配列名结构(比如option1var1拆成option1和var1)
  ) %>%
  # 生成0/1的choice标记:当前option是受访者选的就标1,否则0
  mutate(choice = as.integer(option == as.character(df$choice[respondent]))) %>%
  # 调整列顺序,和你要的目标结构对齐
  select(respondent, choice, option, var1, var2) %>%
  # 把option转成因子,和目标数据结构一致
  mutate(option = factor(option, levels = c("option1", "option2")))

运行完这段代码后,你直接str(long_df)就能看到结果和你期望的完全一致。

关键步骤说明

  • mutate(respondent = row_number()):给每行(每个受访者)生成唯一标识,这是目标数据里必须的列。
  • pivot_longer:这是核心,通过正则表达式自动拆分列名,把option1和option2的对应属性合并到同一列,不用手动拆分再合并。
  • mutate(choice = ...):通过匹配原始选择和当前行的option,快速生成数值型的选择标记。

方法二:用base R

如果你不想加载额外包,用base R的基础函数也能实现,思路是先分别处理两个option的数据,再合并:

# 先添加受访者ID
df$respondent <- 1:nrow(df)

# 处理option1的数据
option1_df <- df[, c("respondent", "choice", "option1var1", "option1var2")]
names(option1_df)[3:4] <- c("var1", "var2")
option1_df$option <- "option1"
option1_df$choice <- as.integer(option1_df$choice == "option1")

# 处理option2的数据
option2_df <- df[, c("respondent", "choice", "option2var1", "option2var2")]
names(option2_df)[3:4] <- c("var1", "var2")
option2_df$option <- "option2"
option2_df$choice <- as.integer(option2_df$choice == "option2")

# 合并两个数据框并排序,调整列顺序
long_df_base <- rbind(option1_df, option2_df)
long_df_base <- long_df_base[order(long_df_base$respondent, long_df_base$option), ]
long_df_base$option <- factor(long_df_base$option, levels = c("option1", "option2"))
long_df_base <- long_df_base[, c("respondent", "choice", "option", "var1", "var2")]

这个方法虽然代码稍长,但逻辑很直观,适合不想依赖第三方包的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:01:22