如何转置LimeSurvey排名数据并将单元格值转为列名?
处理LimeSurvey排名数据的转置需求
我在LimeSurvey中收集了一些排名数据,X1到X9代表项目的排名等级,原始数据结构如下:
structure(list(id = c(1L, 2L, 3L, 4L, 5L, 7L), X1 = c("Parque Arví", "Parque Explora", "Jardín Botánico", "Parque Explora", "Parque Arví", "Parque Arví"), X2 = c("Jardín Botánico", "Jardín Botánico", "Parque Explora", "Jardín Botánico", "Parques del Río", "Jardín Botánico" ), X3 = c("Parques del Río", "Parque Arví", "Parque natural Cerro Volador", "Parques del Río", "Jardín Botánico", "Parque de los Pies Descalzos" ), X4 = c("Parque de los Pies Descalzos", "Parque natural Cerro Volador", "Parque Arví", "Parque Norte", "Parque Llerás", "Parque Explora" ), X5 = c("Parque de la Luz", "Parque Llerás", "Parque Norte", "Parque natural Cerro Volador", "Parque Norte", "Parque natural Cerro Volador" ), X6 = c("Parque Explora", "Parque de los Pies Descalzos", "Parques del Río", "Parque de la Luz", "Parque Explora", "Parques del Río"), X7 = c("Parque natural Cerro Volador", "Parque Norte", "Parque de los Pies Descalzos", "Parque de los Pies Descalzos", "Parque de la Luz", "Parque de la Luz"), X8 = c("Parque Norte", "Parques del Río", "Parque de la Luz", "Parque Arví", "Parque de los Pies Descalzos", "Parque Norte"), X9 = c("Parque Llerás", "Parque de la Luz", "Parque Llerás", "Parque Llerás", "Parque natural Cerro Volador", "Parque Llerás")), class = "data.frame", row.names = c(NA, -6L ))
需要将数据转置,把原数据框的单元格值转为列名,转换后的数据结构如下:
structure(list(id = c(1L, 2L, 3L, 4L, 5L, 7L), Jardín.Botánico = c(2L, 2L, 1L, 2L, 3L, 2L), Parque.Arví = c(1L, 3L, 4L, 8L, 1L, 1L), Parque.de.la.Luz = c(5L, 9L, 8L, 6L, 7L, 7L), Parque.de.los.Pies.Descalzos = c(4L, 6L, 7L, 7L, 8L, 3L), Parque.Explora = c(6L, 1L, 2L, 1L, 6L, 4L), Parque.Llerás = c(9L, 5L, 9L, 9L, 4L, 9L), Parque.natural.Cerro.Volador = c(7L, 4L, 3L, 5L, 9L, 5L), Parque.Norte = c(8L, 7L, 5L, 4L, 5L, 8L), Parques.del.Río = c(3L, 8L, 6L, 3L, 2L, 6L)), class = "data.frame", row.names = c(NA, -6L))
之前找到的方案生成的列名是V1、V2这类,无法显示正确名称,请问如何实现上述需求?
解决方案
方法1:使用tidyverse工具链(推荐)
利用tidyr的行列转换函数,步骤清晰易读:
library(tidyverse) # 假设原始数据框名为df df <- structure(...) # 替换为你的原始数据结构 result_df <- df %>% # 将宽格式转为长格式,提取排名和对应地点 pivot_longer(cols = starts_with("X"), names_to = "rank", values_to = "place") %>% # 从X1/X2等提取纯数字排名 mutate(rank = parse_number(rank)) %>% # 转回宽格式,用地点作为列名,排名作为值,空格替换为点号 pivot_wider(names_from = "place", values_from = "rank", names_sep = ".") # 查看结果 result_df
方法2:使用Base R实现
无需加载额外包,通过基础循环和矩阵操作完成:
# 原始数据框df df <- structure(...) # 分离id列和排名列 id_col <- df$id rank_cols <- df[, -1] # 初始化结果数据框 result_df <- data.frame(id = id_col) # 遍历所有唯一地点名称 unique_places <- unique(unlist(rank_cols)) for (place in unique_places) { # 对每一行,找到该地点对应的排名,空格替换为点号作为列名 result_df[, gsub(" ", ".", place)] <- apply(rank_cols, 1, function(row) which(row == place)) } # 按列名排序(可选,匹配目标结构的列顺序) result_df <- result_df[, c("id", sort(colnames(result_df)[-1]))] # 查看结果 result_df
两种方法均可生成目标结构,列名自动将空格替换为点号,与需求一致。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

