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

如何用pivot_longer将树木属性宽表转为单树一行的长表

解决宽表转长表的pivot_longer使用问题

首先修正你的测试数据代码(原代码存在格式问题,调整为更规范的tidyverse写法):

library(tidyverse)

# 修正后的测试数据
test <- tibble(
  Plot_n = c("Plot1", "Plot2", "Plot3"),
  Tree1_spp = c("Abc", "Cde", "Efg"),
  Tree1_dbh1 = c(10, 15, 20),
  Tree1_dbh2 = c(15, 20, 25),
  Tree1_planted_or_not = c(1, 0, 1),
  Tree2_spp = c("Efg", "Cde", "Abc"),
  Tree2_dbh1 = c(25, 20, 15),
  Tree2_dbh2 = c(20, 15, 10),
  Tree2_planted_or_not = c(1, 0, 1)
)

接下来是正确的pivot_longer调用,核心是用精准的正则拆分列名:

test_long <- test %>%
  pivot_longer(
    cols = -Plot_n,  # 保留样地列,其余列转长格式
    names_to = c("tree", ".values"),  # 第一个捕获组存树木标识,第二个存属性名
    names_pattern = "^(Tree\\d+)_(.*)$"  # 正则拆分逻辑:TreeX + 属性部分
  )

# 查看转换结果
test_long

原代码问题分析

你之前用的正则^([^_\n]+_).*(.*)有两个关键错误:

  1. 第一个捕获组[^_\n]+_会把Tree1_(包含下划线)作为tree列的值,不符合需求;
  2. 中间多余的.*会打乱属性名的捕获逻辑,导致无法正确识别planted_or_not这类带下划线的属性。

正则表达式解释

^(Tree\\d+)_(.*)$的具体含义:

  • ^:匹配列名开头
  • (Tree\\d+):捕获树木标识(比如Tree1、Tree2),对应tree列
  • _:匹配列名中的固定下划线分隔符
  • (.*):捕获下划线后的所有内容(比如spp、dbh1、planted_or_not),作为新的属性列名
  • $:匹配列名结尾

最终结果结构

转换后的长表完全符合你的要求:

Plot_ntreesppdbh1dbh2planted_or_not
Plot1Tree1Abc10151
Plot1Tree2Efg25201
Plot2Tree1Cde15200
Plot2Tree2Cde20150
Plot3Tree1Efg20251
Plot3Tree2Abc15101

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 21:40:50