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

R语言:如何将含NA的多组配对变量转为长格式数据

问题描述

有一个经过截断和子集化的dataframe,包含3组配对变量:Days1/Days2/Days3分别对应Check1.Survival/Check2.Survival/Check3.Survival,数据中存在NA值。目标是将其转换为长格式tibble,让每组配对变量对应一行。尝试了两段pivot_longer代码,但要么变量配对错误,要么数据格式没变化,求正确解决方法。

尝试过的错误代码

第一段代码

test<-out %>%
  pivot_longer(
    cols = c(Days1:Days10, Check1.Survival:Check10.Survival),
    names_to = c(".value", "rating"),
    names_pattern = "([a-z]+)_*(.+)") %>%
  rename(Days = ays, Survival = heck)

第二段代码

test2<-out%>%
  pivot_longer(
    c(-UID, -Cross, -Rep, -Garden),
    names_to = c(".value", "item"), 
    names_sep = "_"
  ) %>% 
  select(-item)

问题原因

  1. 第一段代码的正则表达式([a-z]+)只匹配小写字母,但变量名都是大写开头(比如Days、Check),根本匹配不到完整前缀,导致后续重命名只能拿到残缺的字符串,完全没法正确分组。
  2. 第二段代码用_作为分隔符,但Check1.Survival里是.而非_,Days1更是没有分隔符,拆分逻辑完全不适用,自然转不成想要的长格式。

正确解决方案

方法一:正则匹配一键转换(推荐)

用names_pattern精准拆分变量名的前缀和数字编号,让同编号的配对变量自动归到同一行:

library(tidyr)
library(dplyr)

long_df <- out %>%
  pivot_longer(
    cols = starts_with(c("Days", "Check")), # 选中所有目标配对变量
    names_to = c(".value", "group_num"),    # .value保留变量前缀,group_num提取数字编号
    names_pattern = "(.*?)(\\d+)"            # 正则拆分:(前缀部分)(数字编号)
  ) %>%
  rename(Survival = Check.Survival)         # 把Check.Survival重命名为简洁的Survival

逻辑说明

  • names_pattern = "(.*?)(\\d+)":.*?是非贪婪匹配,会精准抓取数字前的所有内容(比如Check1.Survival拆成Check.Survival,Days1拆成Days);\\d+匹配后面的数字编号。
  • .value会将相同前缀的列合并成新列,同时通过group_num把同编号的Days和Survival配对到同一行,最终每行就是一组完整的配对数据,同时保留UID/Cross/Rep/Garden这些分组变量。

方法二:分步拆分合并(适合正则新手)

如果对正则不太熟悉,可以拆分处理再合并:

library(tidyr)
library(dplyr)

# 处理Days列,转成长格式并提取数字编号
days_long <- out %>%
  select(UID, Cross, Rep, Garden, starts_with("Days")) %>%
  pivot_longer(
    cols = starts_with("Days"),
    names_to = "group_num",
    names_prefix = "Days", # 去掉Days前缀,只留数字编号
    values_to = "Days"
  )

# 处理Survival列,转成长格式并提取数字编号
survival_long <- out %>%
  select(UID, Cross, Rep, Garden, starts_with("Check")) %>%
  pivot_longer(
    cols = starts_with("Check"),
    names_to = "group_num",
    names_pattern = "Check(\\d+).Survival", # 提取数字编号
    values_to = "Survival"
  )

# 按分组变量和编号合并数据
long_df <- inner_join(days_long, survival_long, by = c("UID", "Cross", "Rep", "Garden", "group_num"))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 12:03:24