【问题标题】:Calculate values based on matched substrings within names根据名称中匹配的子字符串计算值
【发布时间】:2022-08-23 12:19:09
【问题描述】:

我试图用匹配的子字符串识别列名,然后计算这些列中值的差异。

样本数据:

V1_ABC <- c(1,2,3,4)
V2_ABC <- c(2,3,4,5)
V1_WXYZ <- c(10,11,12,13)
V2_WXYZ <- c(11,12,13,14)
Date <- c(2001,2002,2003,2004)

所以 df 看起来像:

df <- data.frame(Date, V1_ABC, V2_ABC, V1_WXYZ, V2_WXYZ)

  Date V1_ABC V2_ABC V1_WXYZ V2_WXYZ
1 2001      1      2     10     11
2 2002      2      3     11     12
3 2003      3      4     12     13
4 2004      4      5     13     14

我想计算 ABC 和 WXYZ 的 V1 减去 V2。我的原始数据集要大得多,因此我不想为每个数据集手动执行此操作。我想自动执行此操作,以便 R 比较列标题并查找哪些列具有相同的结束子字符串(V1_ABC 和 V2_ABC,以及 V1_WXYZ 和 V2_WXYZ),然后从 V1_ 中减去 V2_。像这样:

  Date V1_ABC V2_ABC V1_WXYZ V2_WXYZ dif_ABC dif_WXYZ
1 2001      1      2      10      11      -1       -1
2 2002      2      3      11      12      -1       -1
3 2003      3      4      12      13      -1       -1
4 2004      4      5      13      14      -1       -1

我发现的大多数函数,例如 grep 或 intersect 要么查找您输入的特定字符串,要么返回向量相同的值。

关于如何根据名称/子字符串自动配对的任何想法?

  • \"_\" 之前的所有列前缀和它之后的匹配键吗?

标签: r dataframe


【解决方案1】:

您可以分别堆叠V1 和V2,计算差异,然后将它们重新整形为宽格式。这种方法可以处理任意数量的V1_xxx 和V2_xxx。

library(tidyverse)

df %>%
  pivot_longer(contains("_"), names_to = c(".value", "grp"), names_sep = "_") %>%
  mutate(dif = V1 - V2) %>%
  pivot_wider(names_from = grp, values_from = c(V1, V2, dif))

# # A tibble: 4 × 7
#    Date V1_ABC V1_WXYZ V2_ABC V2_WXYZ dif_ABC dif_WXYZ
#   <dbl>  <dbl>   <dbl>  <dbl>   <dbl>   <dbl>    <dbl>
# 1  2001      1      10      2      11      -1       -1
# 2  2002      2      11      3      12      -1       -1
# 3  2003      3      12      4      13      -1       -1
# 4  2004      4      13      5      14      -1       -1

【讨论】:

  • 这可能是比我自己的方法更好的方法(前提是数据不是太大以至于重塑不是不可能的)。我唯一要补充的是,您可能无法将-Date 用于cols 参数,具体取决于数据中的其他列,您可能需要执行cols = matches("_.+$") 之类的操作。
【解决方案2】:

这是一个基本的 R 解决方案。您提到您的数据框很大,因此这会检查恰好有 2 个共享后缀的列并且仅对这些后缀进行操作。它假定它们都是"V1_suffix" 和"V2_suffix" 格式,但如果它们是其他格式,则可以轻松修改。

suffixes <- unlist(regmatches(names(df), gregexpr("_.+", names(df))))

# Limit to suffixes where there are 2
suffixes <- names(table(suffixes)[table(suffixes) == 2])

diffs  <- sapply(suffixes, 
    \(suffix) df[[paste0("V1", suffix)]] - df[[paste0("V2", suffix)]]
)


diff_df  <- data.frame(diffs)  |> 
    setNames(paste0("dif", suffixes))

cbind(df, diff_df)

#   Date V1_ABC V2_ABC V1_WXYZ V2_WXYZ dif_ABC dif_WXYZ
# 1 2001      1      2      10      11      -1       -1
# 2 2002      2      3      11      12      -1       -1
# 3 2003      3      4      12      13      -1       -1
# 4 2004      4      5      13      14      -1       -1

【讨论】:

    猜你喜欢
    • 2017-12-23
    • 2021-05-20
    • 1970-01-01
    • 2020-03-12
    • 1970-01-01
    • 2018-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多