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

如何在R语言中重构调查数据的数据框,将位置列转换为项目评分列?

如何在R中重塑李克特量表调查数据的结构

很高兴帮你解决这个数据重塑的问题!你的需求是把记录答题顺序和评分的宽格式数据,转换成以每个项目为列的结构化数据,这在R里有几种常用的实现方式,下面我给你详细演示:

方法一:使用tidyverse工具包(推荐,代码更直观)

tidyverse里的tidyr包专门处理数据重塑,配合dplyr的管道操作,步骤清晰易读:

步骤1:加载包并准备原始数据

# 安装并加载tidyverse(如果还没安装的话)
# install.packages("tidyverse")
library(tidyverse)

# 你的原始数据框
df <- data.frame(userid = c(1, 2, 3), 
                 pos1 = c("itemA_1", "itemB_1", "itemA_2"), 
                 pos2 = c("itemB_1", "itemC_2", "itemC_1"), 
                 pos3 = c("itemC_5", "itemA_4", "itemB_3") )

步骤2:将宽格式转为长格式

把pos1、pos2、pos3这些列合并成一列,方便后续拆分:

df_long <- df %>%
  pivot_longer(
    cols = starts_with("pos"),  # 选择所有以pos开头的列
    names_to = "position",      # 原列名存到position列
    values_to = "item_score"    # 原列值存到item_score列
  )

步骤3:拆分项目与评分

把item_score列里的itemX_Y拆分成项目名(item)和评分(score),并把评分转为数值型:

df_split <- df_long %>%
  separate(
    item_score, 
    into = c("item", "score"),  # 拆分后生成两列
    sep = "_"                   # 按下划线拆分
  ) %>%
  mutate(score = as.integer(score))  # 把评分转成整数

步骤4:转回目标宽格式

把每个项目作为单独的列,每个用户的评分对应到相应列:

df_final <- df_split %>%
  pivot_wider(
    names_from = item,  # 用item列的值作为新列名
    values_from = score # 用score列的值填充新列
  )

运行后得到的结果:

> df_final
# A tibble: 3 × 4
  userid itemA itemB itemC
   <dbl> <int> <int> <int>
1      1     1     1     5
2      2     4     1     2
3      3     2     3     1

注:你提供的示例结果里部分评分和原始数据不符(比如用户1的itemB评分应为1而非3),上面是基于你给出的原始数据生成的正确结果。

方法二:使用base R(无需额外安装包)

如果你不想安装第三方包,也可以用base R的reshape函数和字符串拆分功能实现:

# 原始数据
df <- data.frame(userid = c(1, 2, 3), 
                 pos1 = c("itemA_1", "itemB_1", "itemA_2"), 
                 pos2 = c("itemB_1", "itemC_2", "itemC_1"), 
                 pos3 = c("itemC_5", "itemA_4", "itemB_3") )

# 1. 转成长格式
df_long_base <- reshape(
  df,
  direction = "long",
  varying = list(names(df)[-1]),  # 指定要转换的列(除了userid)
  v.names = "item_score",
  idvar = "userid",
  timevar = "position"
)

# 2. 拆分项目和评分
split_cols <- do.call(rbind, strsplit(as.character(df_long_base$item_score), "_"))
df_split_base <- cbind(df_long_base["userid"], split_cols)
names(df_split_base) <- c("userid", "item", "score")
df_split_base$score <- as.integer(df_split_base$score)

# 3. 转回宽格式
df_final_base <- reshape(
  df_split_base,
  direction = "wide",
  idvar = "userid",
  timevar = "item",
  v.names = "score"
)

# 去掉列名里的"score."前缀
names(df_final_base) <- gsub("score\\.", "", names(df_final_base))

运行后得到的结果和tidyverse方法完全一致:

> df_final_base
  userid itemA itemB itemC
1      1     1     1     5
2      2     4     1     2
3      3     2     3     1

内容的提问来源于stack exchange,提问作者D. Studer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 11:42:29