首页 > 解决方案 > R:基于列名计算的函数

问题描述

我有一个看起来像这样的数据框(只是一个子样本)

Year <- c(1990,1991,1992)
Country_1_v1 <- c(0.2,0.3,0.4)
Country_1_v2 <- c(0.6,0.5,0.1)
Country_2_v1 <- c(1.2,1.4,1.1)
Country_2_v2 <- c(1.7,1.3,1.2)

因此,我在特定时间段内为两个国家(即 4 列)提供了两列(v1、v2)。现在,我想计算每个国家/地区的 v1/v2。由于我有 25 个国家/地区,因此我不想使用 mutate。

有没有一种快速的方法来构建一个适合我的功能?我对功能不是很熟悉,希望有任何帮助!

现在我的列名是 v1 的“'Country Name'.x”和 v2 的“'Country Name'.y”。

谢谢!

标签: r

解决方案


将 TO 的向量转换为数据框:

dat <- data.frame(Year = c(1990,1991,1992),
                  Country_1_v1 = c(0.2,0.3,0.4),
                  Country_1_v2 = c(0.6,0.5,0.1),
                  Country_2_v1 = c(1.2,1.4,1.1),
                  Country_2_v2 = c(1.7,1.3,1.2))

然后,您可以利用 tidyverse 灵活的方法进行旋转。您需要为此创建一个模板,告诉我们您希望如何将旧变量转换为新变量(我很好奇是否有一种解决方案可以在没有模板的情况下直接将数据转换为 pivot_longer)。

template <- data.frame(.name  = colnames(dat)[-1],
                       Country = c("Country_1", "Country_1", "Country_2", "Country_2"),
                      .value = c("v1", "v2", "v1", "v2"))

这看起来像:

         .name   Country .value
1 Country_1_v1 Country_1     v1
2 Country_1_v2 Country_1     v2
3 Country_2_v1 Country_2     v1
4 Country_2_v2 Country_2     v2

因此,您的每个原始列都分为 a) 国家列和 b) 两个单独的 va 和 v2 列。

现在您可以进行计算并转换回宽格式。

library(tidyverse)
dat %>%
  pivot_longer_spec(template) %>%
  mutate(ratio = v1/v2) %>%
  pivot_wider(names_from = Country,
              values_from = c(v1, v2, ratio),
              names_glue = "{Country}_{.value}")

这使:

# A tibble: 3 x 7
   Year Country_1_v1 Country_2_v1 Country_1_v2 Country_2_v2 Country_1_ratio Country_2_ratio
  <dbl>        <dbl>        <dbl>        <dbl>        <dbl>           <dbl>           <dbl>
1  1990          0.2          1.2          0.6          1.7           0.333           0.706
2  1991          0.3          1.4          0.5          1.3           0.6             1.08 
3  1992          0.4          1.1          0.1          1.2           4               0.917

请注意,这些列的顺序不再与原始数据框中的顺序相同。但这可以通过重新定位管道来解决。


推荐阅读