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

使用pivot_longer处理数据框时出现重复行的问题求助

问题:pivot_longer处理后出现“重复行”,distinct()无效

问题说明

用pivot_longer整理数据框后,每个植物物种都出现了多行,看起来像是重复,但用distinct()去重完全没效果。

数据样本

# 数据预览
# A tibble: 10 × 6
   latin_name           plant_type treatment       `ounces per plot` weight            `grams per plot`
   <chr>                <chr>      <chr>                       <dbl> <chr>                        <dbl>
 1 Agastache foeniculum wildflower tx._one_rate               0.021  wt_per_plot_one              0.609
 2 Agastache foeniculum wildflower tx._one_rate               0.021  wt_per_plot_two              1.22 
 3 Agastache foeniculum wildflower tx._one_rate               0.021  wt_per_plot_three            1.83 
 4 Agastache foeniculum wildflower tx._one_rate               0.021  wt_per_plot_four             2.44 
 5 Agastache foeniculum wildflower tx._two._rate              0.0430 wt_per_plot_one              0.609
 6 Agastache foeniculum wildflower tx._two._rate              0.0430 wt_per_plot_two              1.22 
 7 Agastache foeniculum wildflower tx._two._rate              0.0430 wt_per_plot_three            1.83 
 8 Agastache foeniculum wildflower tx._two._rate              0.0430 wt_per_plot_four             2.44 
 9 Agastache foeniculum wildflower tx._three._rate            0.0645 wt_per_plot_one              0.609
10 Agastache foeniculum wildflower tx._three._rate            0.0645 wt_per_plot_two              1.22 

我使用的代码

library(tidyverse)
seed_rate1 <- seed_rate1%>%
  pivot_longer(
    cols = starts_with("tx"),
    names_to = "treatment",
    values_to = "ounces per plot")%>%
  pivot_longer(
    cols = starts_with("wt"),
    names_to = "weight",
    values_to = "grams per plot")

完整数据(dput输出)

seed_struct <- 
  structure(structure(
    list(
      latin_name = c(
        "Agastache foeniculum",
        "Agastache foeniculum",
        "Agastache foeniculum",
        "Agastache foeniculum",
        "Agastache foeniculum",
        "Agastache foeniculum",
        "Agastache foeniculum",
        "Agastache foeniculum",
        "Agastache foeniculum",
        "Agastache foeniculum",
        "Agastache foeniculum",
        "Agastache foeniculum"
      ),
      plant_type = c(
        "wildflower",
        "wildflower",
        "wildflower",
        "wildflower",
        "wildflower",
        "wildflower",
        "wildflower",
        "wildflower",
        "wildflower",
        "wildflower",
        "wildflower",
        "wildflower"
      ),
      treatment = c(
        "tx._one_rate",
        "tx._one_rate",
        "tx._one_rate",
        "tx._one_rate",
        "tx._two._rate",
        "tx._two._rate",
        "tx._two._rate",
        "tx._two._rate",
        "tx._three._rate",
        "tx._three._rate",
        "tx._three._rate",
        "tx._three._rate"
      ),
      `ounces per plot` = c(
        0.021,
        0.021,
        0.021,
        0.021,
        0.042975207,
        0.042975207,
        0.042975207,
        0.042975207,
        0.06446281,
        0.06446281,
        0.06446281,
        0.06446281
      ),
      weight = c(
        "wt_per_plot_one",
        "wt_per_plot_two",
        "wt_per_plot_three",
        "wt_per_plot_four",
        "wt_per_plot_one",
        "wt_per_plot_two",
        "wt_per_plot_three",
        "wt_per_plot_four",
        "wt_per_plot_one",
        "wt_per_plot_two",
        "wt_per_plot_three",
        "wt_per_plot_four"
      ),
      `grams per plot` = c(
        0.609,
        1.218,
        1.827,
        2.437,
        0.609,
        1.218,
        1.827,
        2.437,
        0.609,
        1.218,
        1.827,
        2.437
      )
    ),
    row.names = c(NA,-12L),
    class = c("tbl_df", "tbl", "data.frame")
  ))

解决建议

先搞清楚:你看到的不是“重复行”

distinct()默认会对比所有列,只有完全一模一样的行才会被去重。你提供的12行数据里,treatment或weight列的值都不一样,所以每一行都是唯一的,distinct()自然没用。你觉得“重复”是因为同一个treatment下的ounces per plot值相同,同一个weight下的grams per plot值相同,但整行并不重复。

针对你的需求,分两种情况处理:

情况1:不需要treatment和weight的所有组合

如果你只想保留treatment的信息(不需要weight相关列),直接去掉weight列再去重:

seed_rate1 %>%
  pivot_longer(
    cols = starts_with("tx"),
    names_to = "treatment",
    values_to = "ounces per plot"
  ) %>%
  select(-starts_with("wt")) %>% # 移除所有weight相关列
  distinct() # 现在可以去重,因为同一treatment的行完全相同

如果你只想保留weight的信息(不需要treatment列):

seed_rate1 %>%
  pivot_longer(
    cols = starts_with("wt"),
    names_to = "weight",
    values_to = "grams per plot"
  ) %>%
  select(-starts_with("tx")) %>% # 移除所有treatment相关列
  distinct()

情况2:原始宽格式数据下,避免笛卡尔积

你用两次pivot_longer的操作,会把每个treatment和每个weight做全组合(笛卡尔积),这就是为什么会生成3个treatment × 4个weight = 12行。如果你的原始宽数据中,tx_*和wt_*是成对关联的(比如tx_one_rate对应wt_per_plot_one),那应该用一次pivot_longer完成转换,避免生成多余组合:

假设你的原始宽数据是这样的:

# 模拟原始宽格式数据
original_wide <- tibble(
  latin_name = "Agastache foeniculum",
  plant_type = "wildflower",
  tx_one_rate = 0.021,
  wt_per_plot_one = 0.609,
  tx_two_rate = 0.043,
  wt_per_plot_two = 1.22,
  tx_three_rate = 0.0645,
  wt_per_plot_three = 1.83,
  tx_four_rate = 0.086,
  wt_per_plot_four = 2.44
)

用一次pivot_longer匹配成对的列:

original_wide %>%
  pivot_longer(
    cols = -c(latin_name, plant_type),
    names_to = c(".value", "group"),
    # 用正则匹配列名的前缀(tx或wt)和后缀(one/two/three/four)
    names_pattern = "(tx.*rate|wt_per_plot)_(.*)"
  ) %>%
  # 重命名列名让结果更清晰
  rename(treatment = tx_one_rate, `grams per plot` = wt_per_plot)

这样就能得到每行对应一组treatment和weight的关联数据,不会生成多余的组合。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 16:25:22