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

如何将横向位置数据转为纵向并过滤空值(R语言)

R语言:将横向位置数据转换为纵向长表并过滤空值

原始数据

actor_data <- structure(list(id = c(123L, 456L, 789L, 912L, 235L), name = c("Tom Cruise", 
"Will Smith", "Ryan Reynolds", "Chris Rock", "Emma Stone"), locationid1 = c(5459L, 
NA, 6114L, NA, NA), location1 = c("Paris, France", "", "Brooklyn, NY", 
"", ""), locationid2 = c(NA, 5778L, NA, NA, 4432L), location3 = c("", 
"Dolby Theater", "", "", "Hollywood"), locationid3 = c(NA, 2526L, 
3101L, NA, NA), location3.1 = c("", "London", "Boston", "", ""
), locationid4 = c(6667L, 2333L, 1118L, NA, NA), location4 = c("Virginia", 
"Maryland", "Washington", "", "")), class = "data.frame", row.names = c(NA, 
-5L))

目标需求

将数据中横向存储的locationid*与对应location*字段转换为纵向结构,同时排除含NA或空字符串的无效记录,最终得到如下长表:

actor_data_exp <- structure(list(id = c(123L, 123L, 456L, 456L, 456L, 789L, 789L, 
789L, 235L), name = c("Tom Cruise", "Tom Cruise", "Will Smith", 
"Will Smith", "Will Smith", "Ryan Reynolds", "Ryan Reynolds", 
"Ryan Reynolds", "Emma Stone"), locationid = c(5459L, 6667L, 
5778L, 2526L, 2333L, 6114L, 3101L, 1118L, 4432L), location = c("Paris, France", 
"Virginia", "Dolby Theater", "London", "Maryland", "Brooklyn, NY", 
"Boston", "Washington", "Hollywood")), class = "data.frame", row.names = c(NA, 
-9L))

解决方案

方法1:使用tidyverse包(推荐)

先统一列名,让location与locationid的后缀编号一一对应,再通过pivot_longer实现宽表转长表,最后过滤无效记录:

library(tidyverse)

# 统一列名,修正location列的编号对应关系
actor_data_rename <- actor_data %>%
  rename(location2 = location3, location3 = location3.1)

# 转换为长表并过滤无效值
actor_data_exp <- actor_data_rename %>%
  pivot_longer(
    cols = starts_with(c("locationid", "location")),
    names_to = c(".value", "num"),
    names_pattern = "(locationid|location)(\\d+)"
  ) %>%
  filter(!is.na(locationid), location != "") %>%
  select(-num) %>%
  arrange(id)

方法2:使用Base R

通过匹配locationid与location列的对应关系,生成多个子数据框后合并,再过滤无效记录:

# 定义基础列和位置相关列
id_cols <- c("id", "name")
loc_id_cols <- grep("locationid", names(actor_data), value = TRUE)
loc_cols <- c("location1", "location3", "location3.1", "location4")

# 生成对应的数据框列表并合并
df_list <- Map(function(id_col, loc_col) {
  temp <- actor_data[, c(id_cols, id_col, loc_col)]
  names(temp)[3:4] <- c("locationid", "location")
  temp
}, loc_id_cols, loc_cols)

# 合并后过滤无效记录
actor_data_exp <- do.call(rbind, df_list) %>%
  filter(!is.na(locationid), location != "") %>%
  arrange(id)

验证结果

执行以下代码可确认转换结果与目标结构一致:

all.equal(actor_data_exp, structure(list(id = c(123L, 123L, 456L, 456L, 456L, 789L, 789L, 
789L, 235L), name = c("Tom Cruise", "Tom Cruise", "Will Smith", 
"Will Smith", "Will Smith", "Ryan Reynolds", "Ryan Reynolds", 
"Ryan Reynolds", "Emma Stone"), locationid = c(5459L, 6667L, 
5778L, 2526L, 2333L, 6114L, 3101L, 1118L, 4432L), location = c("Paris, France", 
"Virginia", "Dolby Theater", "London", "Maryland", "Brooklyn, NY", 
"Boston", "Washington", "Hollywood")), class = "data.frame", row.names = c(NA, 
-9L)))
# 返回TRUE表示结果匹配

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 14:55:24