tidyr 提取正则表达式

tidyr extract regular expression

我有一个数据框,其中包含一些变量和场景的一些统计信息。数据如下:

df <- data.frame(
  Scenario = c('base','stress','extreme'),
  x_min = c(-3,-2, -2.5),
  x_mean = c(0,0.25, 1),
  x_max = c(2, 1, 3),
  y_min = c(-1.5, -2, -3),
  y_mean = c(1, 2, 3),
  y_max = c(5, 3, 3.5),
  z_min = c(0, 1, 3),
  z_mean = c(0.25, 2, 5),
  z_max = c(2, 4, 7)
)

   Scenario x_min x_mean x_max y_min y_mean y_max z_min z_mean z_max
1     base  -3.0   0.00     2  -1.5      1   5.0     0   0.25     2
2   stress  -2.0   0.25     1  -2.0      2   3.0     1   2.00     4
3  extreme  -2.5   1.00     3  -3.0      3   3.5     3   5.00     7

我想使用 tidyr 的收集和提取函数(以类似于 Hadley 对 this question 的回答的方式)以如下格式获取数据:

new_df
    Scenario variable  min  mean   max
1     base        x   -3.0  0.00   2.0
2   stress        x   -2.0  0.25   1.0
3  extreme        x   -2.5  1.00   3.0
4     base        y   -1.5  1.00   5.0
5   stress        y   -2.0  2.00   3.0
6  extreme        y   -3.0  3.00   3.5
7     base        z    0.0  0.25   2.0
8   stress        z    1.0  2.00   4.0
9  extreme        z    3.0  5.00   7.0

到目前为止我的命令如下所示:

new_df <- df %>%
            gather(key, value, -Scenario) %>%
            extract(key, c("min", "mean", "max"), "regex")

这是我正在苦苦挣扎的正则表达式。按照上面提到的问题的答案,我试过了:

"_min|_mean|_max" --> idea being to capture the 3 different groups

我得到的错误看起来像:

 Error in names(l) <- into : 
     'names' attribute [3] must be the same length as the vector [0]

我认为这个错误的意思是正则表达式不是 "finding" 3 组来分类到 c("min","mean","max") 我通过它。

什么正则表达式可以让它工作?或者还有其他更好的方法吗?

你只需要

df %>% gather(var, val, -Scenario) %>% 
    separate(var, into = c('var', 'stat'), sep = '_') %>% 
    spread(stat, val)
#   Scenario var max mean  min
# 1     base   x 2.0 0.00 -3.0
# 2     base   y 5.0 1.00 -1.5
# 3     base   z 2.0 0.25  0.0
# 4  extreme   x 3.0 1.00 -2.5
# 5  extreme   y 3.5 3.00 -3.0
# 6  extreme   z 7.0 5.00  3.0
# 7   stress   x 1.0 0.25 -2.0
# 8   stress   y 3.0 2.00 -2.0
# 9   stress   z 4.0 2.00  1.0

由于您的初始列名称格式很好,下划线分隔变量和统计信息,因此您只需 separate 即可将它们分成两列。 spread 将从长到宽重新排列。

这可以通过 data.table 中的 melt 轻松完成,因为它可以在 measure

中占用多个 patterns
library(data.table)
nm1 <- unique(substr(names(df)[-1], 1, 1))
melt(setDT(df), measure = patterns("min$", "mean$", "max$"),
       value.name= c("min", "mean", "max"))[, variable := nm1[variable]][]
#   Scenario variable  min mean max
#1:     base        x -3.0 0.00 2.0
#2:   stress        x -2.0 0.25 1.0
#3:  extreme        x -2.5 1.00 3.0
#4:     base        y -1.5 1.00 5.0
#5:   stress        y -2.0 2.00 3.0
#6:  extreme        y -3.0 3.00 3.5
#7:     base        z  0.0 0.25 2.0
#8:   stress        z  1.0 2.00 4.0
#9:  extreme        z  3.0 5.00 7.0