如果多个数字列的名称共享最后 3 个字符,则合并多个数字列

问题描述 投票:0回答:2

我有一个包含 150 列的数据集,其中列被命名为 Qa101 到 Qa150、Qb101 到 Qb150 和 Qc101 到 Qc150。计划是将名称的最后三个字符(例如 101)共享的列合并起来,并且每 3 个共享最后三个字符的列只有一列,例如 Qa101、Qb101 和 Qc101,应合并为 Q101。的列都是数值,可以肯定的是,这三列中只有一列共享最后三个字符保存值,另外两列为 NA,例如 Qa101 为数值,Qb101 和 Qc101 为 NA,等等在。 我希望找到一个 tidyverse 解决方案,但在这个阶段我会接受任何事情。

我已经使用 dplyr 函数尝试了不同的不成功方法,例如:

data.test <- data %>%
  mutate(across(where(~str_match(., start=-3))),unite(remove= TRUE, na.rm=TRUE),.keep = "none") 

但这显然是错误的。

r dplyr stringr
2个回答
0
投票

一个

tidyverse
示例。
data
由 150 列组成,按照您的问题命名,只有“Qb”列不是
NA

library(tidyverse)

data <- data.frame(matrix(1:450, nrow = 3, ncol = 150))

data[, c(1:50, 101:150)] <- NA

names(data) <-
    paste(rep(c("Qa", "Qb", "Qc"), each = length(101:150)), 101:150, sep = "")

的想法是使用

pivot_longer()
,然后连接相关列的值。最后,我们使用
pivot_wider()
将其转换回来。

data |>
    mutate(id = row_number()) |>
    pivot_longer(
        cols = c(-id),
        names_to = "colname",
        values_to = c("value")
    ) |>
    mutate(helper = str_c(str_sub(colname, 1, 1), str_sub(colname, -3, -1))) |>
    filter(!is.na(value))  |>
    select(-c(colname)) |>
    distinct() |>
    pivot_wider(names_from = helper, values_from = value) |>
    select(-id)

# A tibble: 3 × 50
   Q101  Q102  Q103  Q104  Q105  Q106  Q107  Q108  Q109  Q110  Q111  Q112  Q113  Q114  Q115
  <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
1   151   154   157   160   163   166   169   172   175   178   181   184   187   190   193
2   152   155   158   161   164   167   170   173   176   179   182   185   188   191   194
3   153   156   159   162   165   168   171   174   177   180   183   186   189   192   195
# ℹ 35 more variables: Q116 <int>, Q117 <int>, Q118 <int>, Q119 <int>, Q120 <int>,
#   Q121 <int>, Q122 <int>, Q123 <int>, Q124 <int>, Q125 <int>, Q126 <int>, Q127 <int>,
#   Q128 <int>, Q129 <int>, Q130 <int>, Q131 <int>, Q132 <int>, Q133 <int>, Q134 <int>,
#   Q135 <int>, Q136 <int>, Q137 <int>, Q138 <int>, Q139 <int>, Q140 <int>, Q141 <int>,
#   Q142 <int>, Q143 <int>, Q144 <int>, Q145 <int>, Q146 <int>, Q147 <int>, Q148 <int>,
#   Q149 <int>, Q150 <int>

0
投票

如上所述:

可以肯定的是,这三列中只有一列共享最后三个字符(例如

Qa101
Qb101
Qc101
)持有值,另外两列是 NA。

我创建了一个最小的示例数据集:

set.seed(123)
df <- as.data.frame(
  matrix(t(replicate(9, sample(c(sample(1:10, 1), NA, NA)))), 3, 9,
         dimnames = list(NULL, paste0(rep(c("Qa", "Qb", "Qc"), each = 3), 101:103)))
)

#   Qa101 Qa102 Qa103 Qb101 Qb102 Qb103 Qc101 Qc102 Qc103
# 1    NA    NA    NA     3    NA     8    NA    10    NA
# 2    NA    NA    NA     2     3     9    NA    NA    NA
# 3    NA     9    NA    NA    NA     1     4    NA    NA

解决方案

您可以

pivot_longer()
处理列组,然后
summarise()
按行 ID 保留唯一的非缺失值。

library(tidyverse)

df %>%
  mutate(ID = row_number()) %>%
  pivot_longer(matches("Q[abc]"),
               names_to = c(NA, ".value"),
               names_pattern = "(\\D+)(\\d+)") %>%
  summarise(across(`101`:`103`, ~ .x[!is.na(.x)][1], .names = "Q{.col}"),
            .by = ID)

#      ID  Q101  Q102  Q103
#   <int> <int> <int> <int>
# 1     1     3    10     8
# 2     2     2     3     9
# 3     3     4     9     1
© www.soinside.com 2019 - 2024. All rights reserved.