tidyr提取物正则表达式

时间:2016-05-13 16:47:41

标签: regex r dplyr extract tidyr

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

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]

我认为这个错误说的是正则表达式没有“找到”3个组来排序到我传递的c("min","mean","max")

什么正则表达式可以使这个工作?还是有另一种更好的方法吗?

2 个答案:

答案 0 :(得分:3)

你需要的只是

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将从长到宽重新排列。

答案 1 :(得分:2)

可以使用melt中的data.table轻松完成此操作,因为patterns

可能需要多个measure
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