2016-05-13 16 views
3

我有一個數據框,其中包含一些變量和場景的一些統計數據。數據是這樣的: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的收集和提取功能(類似的方式來哈德利的答案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")

什麼正則表達式會得到這個工作?或者還有另一種更好的方法?

回答

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

正是我需要的!作爲一個說明,我必須使'separate'的sep參數成爲正則表達式,因爲我的列標題實際上包含多個下劃線(例如'stat_1_min,stat_2_min')。我使用的正則表達式是'(_)(?!。* _)' – reidjax

2

這可以很容易地從meltdata.table來完成,因爲它可以採取多種patternsmeasure

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