dplyr | tidyverse: объединить наборы пар ключ-значение в один ключ-значение (длинный формат) - PullRequest
0 голосов
/ 28 мая 2018

Каков канонический dplyr или tidyverse способ объединения двух наборов данных пары ключ-значение?

Первая пара ключ-значение - parameter - coeft.

Вторая пара ключ-значение - param - value.Складка заключается в том, что эти значения дублируются.

Я хотел бы объединить их в одну пару ключ-значение.

dat <- tidyr::crossing(sim=c(1:5), 
                parameter=c('mu','sigma'), 
                param=c('sd','sd')
                ) %>%
        dplyr::mutate(coeft=rnorm(n=10)) %>%
        dplyr::mutate(value=sort(rep(rnorm(n=5),2)))
> dat
# A tibble: 10 x 5
  sim parameter param  coeft   value
  <int> <chr>     <chr>  <dbl>   <dbl>
1     1 mu        sd    -1.91  -0.601 
2     1 sigma     sd    -0.967 -0.601 
3     2 mu        sd    -1.95   0.0645
4     2 sigma     sd     0.676  0.0645
5     3 mu        sd    -0.891  0.673 
6     3 sigma     sd    -0.328  0.673 
7     4 mu        sd    -2.30   1.08  
8     4 sigma     sd     0.679  1.08  
9     5 mu        sd    -0.598  1.99  
10     5 sigma     sd    -0.339  1.99 

Желаемая структура:

# A tibble: 15 x 3
  sim parameter   coeft
  <int> <chr>     <dbl>
1     1 mu       -1.91
2     1 sigma    -0.967  
3     1 sd       -0.601
4     2 mu       -1.95
5     2 sigma    0.676  
6     2 sd       0.0645
...

Ответы [ 2 ]

0 голосов
/ 28 мая 2018

Вот подход с dplyr (работает с dplyr v0.7.4, Windows 7, R64-bit):

dat %>%
  spread(parameter, coeft) %>% #convert to wide format
  rename(sd = value) %>% #change the name of a column
  gather(parameter, coeft, c(4,5,3)) %>% #convert three disjointly located columns to long format, note the order of columns
  # gather(parameter, coeft, sd:sigma) %>% #convert three contiguously located columns to long format
  arrange(sim) %>% #order of rows
  select(-param) 

Это выдает предупреждение в некоторых версиях dplyr (0.7.4) но не на всех (завтра опубликую одну версию без ошибок - когда я проверю).

warning: Warning message: In if (!is.finite(x)) return(FALSE) : the condition has length > 1 and only the first element will be used

В этом случае это можно запустить без предупреждений:

dat %>%
  spread(parameter, coeft) %>% 
  dplyr::rename(sd = value) %>% 
  gather(parameter, coeft, "mu", "sigma", "sd") %>% 
  arrange(sim) %>% #order of rows
  select(-param) 

Также обратите внимание, что если вы хотите использовать нотацию исключения столбцов, вам необходимо исключить столбец param ранее.

dat %>%
  spread(parameter, coeft) %>% #convert to wide format
  rename(sd = value) %>% #change the name of a column
  select(-param) %>%
  gather(parameter, coeft, -sim) %>% #convert three contiguously located columns to long format
  arrange(sim) #order of rows

#output
     sim parameter  coeft
  <int> <chr>      <dbl>
 1     1 mu        -0.626
 2     1 sigma      0.184
 3     1 sd        -2.21 
 4     2 mu        -0.836
 5     2 sigma      1.60 
 6     2 sd        -0.621
 7     3 mu         0.330
 8     3 sigma     -0.820
 9     3 sd         0.390
10     4 mu         0.487
11     4 sigma      0.738
12     4 sd         1.12 
13     5 mu         0.576
14     5 sigma     -0.305
15     5 sd         1.51 

data:

set.seed(1)
dat <- tidyr::crossing(sim=c(1:5), 
                       parameter=c('mu','sigma'), 
                       param=c('sd','sd')
) %>%
  dplyr::mutate(coeft=rnorm(n=10)) %>%
  dplyr::mutate(value=sort(rep(rnorm(n=5),2)))
0 голосов
/ 28 мая 2018

Если нам нужно преобразовать в «длинный» формат несколько наборов столбцов, тогда melt из data.table - это опция

library(data.table)
dt <- unique(melt(setDT(dat), measure = list(2:3, 4:5),
       value.name = c('parameter', 'coeft')))[, variable := NULL][order(sim)]
dt
#    sim parameter   coeft
# 1:   1        mu -1.9100
# 2:   1     sigma -0.9670
# 3:   1        sd -0.6010
# 4:   2        mu -1.9500
# 5:   2     sigma  0.6760
# 6:   2        sd  0.0645
# 7:   3        mu -0.8910
# 8:   3     sigma -0.3280
# 9:   3        sd  0.6730
#10:   4        mu -2.3000
#11:   4     sigma  0.6790
#12:   4        sd  1.0800
#13:   5        mu -0.5980
#14:   5     sigma -0.3390
#15:   5        sd  1.9900

data

dat <- structure(list(sim = c(1L, 1L, 2L, 2L, 3L, 3L, 4L, 4L, 5L, 5L
), parameter = c("mu", "sigma", "mu", "sigma", "mu", "sigma", 
"mu", "sigma", "mu", "sigma"), param = c("sd", "sd", "sd", "sd", 
"sd", "sd", "sd", "sd", "sd", "sd"), coeft = c(-1.91, -0.967, 
-1.95, 0.676, -0.891, -0.328, -2.3, 0.679, -0.598, -0.339), value = c(-0.601, 
-0.601, 0.0645, 0.0645, 0.673, 0.673, 1.08, 1.08, 1.99, 1.99)), 
.Names = c("sim", 
"parameter", "param", "coeft", "value"),
   class = "data.frame", row.names = c(NA, 
-10L))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...