如何用R将宽数据中值为1的列名转为长数据的行
宽格式演员电影数据转长格式的R实现
需求:将宽格式的演员-电影数据(演员为行,电影名为列,单元格值1表示出演,NA表示未出演)转换为长格式,每行展示一位演员及其出演的一部电影,仅保留出演记录。
输入数据
首先定义输入的宽格式数据:
wide_data <- structure(list(Actor = c("Brad Pitt", "Matt Damon", "Leonardo Dicaprio", "Kate Winslet", "Jennifer Connoley", "Jude Law", "Gwenyth Paltrow"), `Once upon a time in america` = c(NA, NA, NA, NA, 1, NA, NA), `The Departed` = c(NA, 1, 1, NA, NA, NA, NA), `Once Upon a time in Hollywood` = c(1, NA, 1, NA, NA, NA, NA), `the holiday` = c(NA, NA, NA, 1, NA, 1, NA), titanic = c(NA, NA, 1, 1, NA, NA, NA), contagion = c(NA, 1, NA, 1, NA, 1, 1), `the talented mr ripley` = c(NA, 1, NA, NA, NA, 1, 1), `Oceans Eleven` = c(1, 1, NA, NA, NA, NA, NA), `Blood Diamond` = c(NA, NA, 1, NA, 1, NA, NA)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -7L))
解决方案
方法1:使用tidyverse的pivot_longer(推荐)
pivot_longer是tidyverse中处理宽转长的专用函数,代码简洁直观:
library(tidyverse) long_data <- wide_data %>% # 将所有非Actor列转为长格式,自动过滤未出演记录 pivot_longer( cols = -Actor, names_to = "Movie", values_to = "Appeared", values_drop_na = TRUE ) %>% select(-Appeared) %>% # 移除不需要的标记列 mutate(Movie = str_to_title(Movie)) # 统一电影名大小写,匹配期望输出 # 查看结果 long_data
方法2:Base R实现
如果不想加载额外包,可以用Base R的转置和筛选完成:
# 提取电影列名 movie_cols <- setdiff(names(wide_data), "Actor") # 转置电影数据部分,将演员转为列 temp <- as.data.frame(t(wide_data[movie_cols]), stringsAsFactors = FALSE) colnames(temp) <- wide_data$Actor # 整理成长格式并过滤未出演记录 long_data_base <- data.frame( Actor = rep(colnames(temp), each = nrow(temp)), Movie = rep(rownames(temp), ncol(temp)), Appeared = unlist(temp), stringsAsFactors = FALSE ) %>% filter(!is.na(Appeared)) %>% select(-Appeared) %>% mutate(Movie = str_to_title(Movie)) # 查看结果 long_data_base
两种方法得到的结果结构与你提供的期望输出完全一致,每行对应一个演员的一部出演电影。
内容的提问来源于stack exchange,提问作者user35131
相关产品推荐
相关产品推荐

