Как разбить столбец списочных значений на несколько столбцов? - PullRequest
0 голосов
/ 26 апреля 2018

У меня следующая ситуация, столбец power_dbm0 имеет значения в виде списка. Все элементы списка длиной 11.

# A tibble: 10 x 2
   real_pat power_dbm0
   <chr>    <list>    
 1 am       <dbl [11]>
 2 fax      <dbl [11]>
 3 fp       <dbl [11]>
 4 fpw      <dbl [11]>

Я хотел бы знать, как можно разделить эти значения, поскольку каждый ордер является новым столбцом. Предпочтительно, я бы хотел dplyr-подобное решение. Я пробовал некоторые решения с функцией unnest или separate из tidyr, но это не удалось.

Заранее спасибо,

Следуйте за данными:

structure(list(real_pat = c("am", "fax", "fp", "fpw"), power_dbm0 = list(
    structure(c(0.0142857142857143, 0.0742857142857143, 0.111428571428571, 
    0.138571428571429, 0.208571428571429, 0.278571428571429, 
    0.368571428571429, 0.508571428571429, 0.648571428571429, 
    0.771428571428571, 0.871428571428571), .Names = c("0%", "10%", 
    "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"
    )), structure(c(0.342857142857143, 0.342857142857143, 0.342857142857143, 
    0.342857142857143, 0.342857142857143, 0.342857142857143, 
    0.342857142857143, 0.342857142857143, 0.342857142857143, 
    0.342857142857143, 0.342857142857143), .Names = c("0%", "10%", 
    "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"
    )), structure(c(0.0142857142857143, 0.622857142857143, 0.808571428571429, 
    0.851428571428571, 0.857142857142857, 0.871428571428571, 
    0.874285714285714, 0.885714285714286, 0.894285714285714, 
    0.911428571428571, 0.914285714285714), .Names = c("0%", "10%", 
    "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"
    )), structure(c(0.514285714285714, 0.514285714285714, 0.514285714285714, 
    0.514285714285714, 0.514285714285714, 0.514285714285714, 
    0.514285714285714, 0.514285714285714, 0.514285714285714, 
    0.514285714285714, 0.514285714285714), .Names = c("0%", "10%", 
    "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"
    )))), .Names = c("real_pat", "power_dbm0"), row.names = c(NA, 
-4L), class = c("tbl_df", "tbl", "data.frame"))

Ответы [ 3 ]

0 голосов
/ 26 апреля 2018

1) Это базовое решение в одну строку:

with(dd, do.call("rbind", setNames(power_dbm0, real_pat)))

дает:

            0%        10%       20%       30%       40%       50%       60%
am  0.01428571 0.07428571 0.1114286 0.1385714 0.2085714 0.2785714 0.3685714
fax 0.34285714 0.34285714 0.3428571 0.3428571 0.3428571 0.3428571 0.3428571
fp  0.01428571 0.62285714 0.8085714 0.8514286 0.8571429 0.8714286 0.8742857
fpw 0.51428571 0.51428571 0.5142857 0.5142857 0.5142857 0.5142857 0.5142857
          70%       80%       90%      100%
am  0.5085714 0.6485714 0.7714286 0.8714286
fax 0.3428571 0.3428571 0.3428571 0.3428571
fp  0.8857143 0.8942857 0.9114286 0.9142857
fpw 0.5142857 0.5142857 0.5142857 0.5142857

2) или получить real_pat в виде столбца, а не имен:

with(dd, data.frame(real_pat, do.call("rbind", power_dbm0), check.names = FALSE))

дает:

  real_pat         0%        10%       20%       30%       40%       50%
1       am 0.01428571 0.07428571 0.1114286 0.1385714 0.2085714 0.2785714
2      fax 0.34285714 0.34285714 0.3428571 0.3428571 0.3428571 0.3428571
3       fp 0.01428571 0.62285714 0.8085714 0.8514286 0.8571429 0.8714286
4      fpw 0.51428571 0.51428571 0.5142857 0.5142857 0.5142857 0.5142857
        60%       70%       80%       90%      100%
1 0.3685714 0.5085714 0.6485714 0.7714286 0.8714286
2 0.3428571 0.3428571 0.3428571 0.3428571 0.3428571
3 0.8742857 0.8857143 0.8942857 0.9114286 0.9142857
4 0.5142857 0.5142857 0.5142857 0.5142857 0.5142857

3) Используя dplyr, мы могли бы написать это:

library(dplyr)
dd %>% { bind_cols(select(., real_pat), bind_rows(!!!.$power_dbm0)) }

дает:

# A tibble: 4 x 12
  real_pat   `0%`  `10%` `20%` `30%` `40%` `50%` `60%` `70%` `80%` `90%` `100%`
  <chr>     <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>
1 am       0.0143 0.0743 0.111 0.139 0.209 0.279 0.369 0.509 0.649 0.771  0.871
2 fax      0.343  0.343  0.343 0.343 0.343 0.343 0.343 0.343 0.343 0.343  0.343
3 fp       0.0143 0.623  0.809 0.851 0.857 0.871 0.874 0.886 0.894 0.911  0.914
4 fpw      0.514  0.514  0.514 0.514 0.514 0.514 0.514 0.514 0.514 0.514  0.514

3a) или используя аргумент .id= bind_rows и значение magrittr %$%:

library(dplyr)
library(magrittr)

dd %$%
   setNames(power_dbm0, real_pat) %$%
   bind_rows(!!!., .id = "real_pat")

дает:

# A tibble: 4 x 12
  real_pat   `0%`  `10%` `20%` `30%` `40%` `50%` `60%` `70%` `80%` `90%` `100%`
  <chr>     <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>
1 am       0.0143 0.0743 0.111 0.139 0.209 0.279 0.369 0.509 0.649 0.771  0.871
2 fax      0.343  0.343  0.343 0.343 0.343 0.343 0.343 0.343 0.343 0.343  0.343
3 fp       0.0143 0.623  0.809 0.851 0.857 0.871 0.874 0.886 0.894 0.911  0.914
4 fpw      0.514  0.514  0.514 0.514 0.514 0.514 0.514 0.514 0.514 0.514  0.514

3b) или без %$%:

library(dplyr)

dd %>%
   { setNames(.$power_dbm0, .$real_pat) } %>%
   { bind_rows(!!!., .id = "real_pat") }

дает:

# A tibble: 4 x 12
  real_pat   `0%`  `10%` `20%` `30%` `40%` `50%` `60%` `70%` `80%` `90%` `100%`
  <chr>     <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>
1 am       0.0143 0.0743 0.111 0.139 0.209 0.279 0.369 0.509 0.649 0.771  0.871
2 fax      0.343  0.343  0.343 0.343 0.343 0.343 0.343 0.343 0.343 0.343  0.343
3 fp       0.0143 0.623  0.809 0.851 0.857 0.871 0.874 0.886 0.894 0.911  0.914
4 fpw      0.514  0.514  0.514 0.514 0.514 0.514 0.514 0.514 0.514 0.514  0.514
0 голосов
/ 26 апреля 2018

Опция может быть как:

cbind(df[1],t(sapply(df$power_dbm0,function(x)x)))

# real_pat         0%        10%       20%       30%       40%       50%       60%       70%       80%       90%      100%
# 1       am 0.01428571 0.07428571 0.1114286 0.1385714 0.2085714 0.2785714 0.3685714 0.5085714 0.6485714 0.7714286 0.8714286
# 2      fax 0.34285714 0.34285714 0.3428571 0.3428571 0.3428571 0.3428571 0.3428571 0.3428571 0.3428571 0.3428571 0.3428571
# 3       fp 0.01428571 0.62285714 0.8085714 0.8514286 0.8571429 0.8714286 0.8742857 0.8857143 0.8942857 0.9114286 0.9142857
# 4      fpw 0.51428571 0.51428571 0.5142857 0.5142857 0.5142857 0.5142857 0.5142857 0.5142857 0.5142857 0.5142857 0.5142857

Дополнительная опция с использованием simplify2array (на основе отзывов от @@ G.Grothendieck):

cbind(df[1],t(simplify2array(df$power_dbm0)))
0 голосов
/ 26 апреля 2018

1) Мы могли бы transpose столбец 'power_dbm0', unlist список nested и затем связать с первым столбцом

library(tidyverse)
df1 %>%
   pull(power_dbm0) %>%
   transpose %>%
   map_df(unlist) %>% 
   bind_cols(df1[1], .)
# A tibble: 4 x 12
#   real_pat   `0%`  `10%` `20%` `30%` `40%` `50%` `60%` `70%` `80%` `90%` `100%`
#  <chr>     <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>
#1 am       0.0143 0.0743 0.111 0.139 0.209 0.279 0.369 0.509 0.649 0.771  0.871
#2 fax      0.343  0.343  0.343 0.343 0.343 0.343 0.343 0.343 0.343 0.343  0.343
#3 fp       0.0143 0.623  0.809 0.851 0.857 0.871 0.874 0.886 0.894 0.911  0.914
#4 fpw      0.514  0.514  0.514 0.514 0.514 0.514 0.514 0.514 0.514 0.514  0.514

2) Или другой вариант - melt, а затем сделать spread. Здесь мы также включаем unnest в качестве ОП, упомянутого в посте

library(tidyverse)
library(reshape2)
df1 %>% 
    mutate(power_dbm0 = map(power_dbm0, ~melt(.x) %>% 
                          rownames_to_column('rn') %>%
                          mutate(rn = factor(rn, levels = rn)))) %>% 
    unnest %>% 
    spread(rn, value)
# A tibble: 4 x 12
#  real_pat   `0%`  `10%` `20%` `30%` `40%` `50%` `60%` `70%` `80%` `90%` `100%`
#  <chr>     <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>
#1 am       0.0143 0.0743 0.111 0.139 0.209 0.279 0.369 0.509 0.649 0.771  0.871
#2 fax      0.343  0.343  0.343 0.343 0.343 0.343 0.343 0.343 0.343 0.343  0.343
#3 fp       0.0143 0.623  0.809 0.851 0.857 0.871 0.874 0.886 0.894 0.911  0.914
#4 fpw      0.514  0.514  0.514 0.514 0.514 0.514 0.514 0.514 0.514 0.514  0.514

3) Или с pmap и spread

df1 %>%
     pmap_df(~ tibble(real_pat = ..1, nm = names(..2), val = ..2))  %>%
     spread(nm, val)

ПРИМЕЧАНИЕ. Все используемые решения dplyr и соответствующие пакеты в tidyverse


4) Или мы могли бы unlist 'power_dbm0', создать matrix, поскольку все они равной длины, а затем связать с первым столбцом (base R) - Имена столбцов могут может быть изменено при необходимости

data.frame(df1[1], matrix(unlist(df1$power_dbm0), ncol = 11, byrow = TRUE))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...