R:根据变量名称中的字符串将数字数据从列旋转到行

R: Pivot numeric data from columns to rows based on string in variable name

我有一个数据集,我想根据变量名称是否包含任何字符串将其转换为长格式:list_a <- c("a", "b", "c" ) 和 list_b <- c("美元"、"欧元"、"英镑")。数据集仅包含一行中的值。我希望 list_b 中的值成为列名,list_a 中的值成为结果数据集中的行名。请参阅下面的可重现示例数据集。

我目前通过应用以下 R 代码(list_b 中的每个值一次)解决这个问题,产生三个数据帧,分别称为“df_usd”、“df_eur”和“df_gbp”,然后我根据“名称”列合并。然而,这有点麻烦,如果你能帮我找到一个更优雅的解决方案,我将不胜感激,因为 list_b 中的变量每个月都在变化(list_a 每个月保持不变)并且手动更新现有代码既费时又容易出现手动错误。

# Current solution for df_usd:

df_usd <- df %>%
  select(date, contains("usd")) %>% 
  pivot_longer(cols = contains(c("a_", "b_", "c_")),
   names_to = "name", values_to = "usd") %>% mutate(name = case_when(
    str_detect(name, "a_") ~ "a",
    str_detect(name, "b_") ~ "b",
    str_detect(name, "c_") ~ "c")) %>% 
  select(-date)

起点截图Excel

我想要在 Excel 中实现的结果的屏幕截图

# Example data to copy and paste into R for easy reproduction of problem:

df <- data.frame (date  = c("2020-12-31"),
                  a_usd  = c(1000),
                  b_usd = c(2000),
                  c_usd = c(3000),
                  a_eur = c(100),
                  b_eur =c(200),
                  c_eur = c(300),
                  a_gbp = c(10),
                  b_gbp = c(20),
                  c_gbp = c(30))

pivot_longer

中用names_to指定names_sep
library(dplyr)
df %>%
   pivot_longer(cols = -date, names_to = c("grp", ".value"), names_sep = "_")

-输出

# A tibble: 3 x 5
#  date       grp     usd   eur   gbp
#  <chr>      <chr> <dbl> <dbl> <dbl>
#1 2020-12-31 a      1000   100    10
#2 2020-12-31 b      2000   200    20
#3 2020-12-31 c      3000   300    30

使用 reshape

的基础 R 选项
reshape(
  setNames(df, gsub("(\w+)_(\w+)", "\2.\1", names(df))),
  direction = "long",
  varying = -1
)

给予

          date time  usd eur gbp id
1.a 2020-12-31    a 1000 100  10  1
1.b 2020-12-31    b 2000 200  20  1
1.c 2020-12-31    c 3000 300  30  1