我正在尝试创建一个基于另一个数据框内容生成的数据框。在下面的示例中,我使用tibble的n_seqs
列指定rnorm
函数的均值,然后生成my_tibble
。 my_tibble
的第一列应包含group
列中的值,后续列应包含运行rnorm
的10个随机值。正如下面的可重复示例所示,我能够通过一种相当黑客的方法来实现这一点。
我不明白......
pull
并且无法在n_seqs
函数中指定map
。也map_dfr
或bind_rows
dplyr
/ purrr
方法才能获得理想的结果?library(tidyverse)
my_tibble <- tibble(group=c("A", "B", "C"), n_seqs=c(5,7,10)) %>%
pull(n_seqs) %>%
map(function(x){ z <- rnorm(x, n=10); names(z) <- letters[1:10]; return(z) })
my_tibble
#> [[1]]
#> a b c d e f g h
#> 6.518214 4.305639 6.106827 5.118304 4.255043 5.678025 4.345129 4.914239
#> i j
#> 6.727135 6.030590
#>
#> [[2]]
#> a b c d e f g h
#> 7.969410 7.558780 8.265322 8.004338 6.862732 5.517313 8.061683 4.062385
#> i j
#> 6.693430 7.858993
#>
#> [[3]]
#> a b c d e f g
#> 9.066362 9.921300 10.724671 8.643903 9.783747 9.102569 10.489579
#> h i j
#> 9.156070 9.863332 11.148255
#error
my_tibble %>% bind_rows(.)
#> Error in bind_rows_(x, .id): Argument 1 must have names
# deprecated warning, but desired output
my_tibble %>% rbind_list %>% mutate(sample=c("A", "B", "C")) %>% select(sample, everything())
#> Warning: 'rbind_list' is deprecated.
#> Use 'bind_rows()' instead.
#> See help("Deprecated")
#> # A tibble: 3 x 11
#> sample a b c d e f g h i j
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 A 6.52 4.31 6.11 5.12 4.26 5.68 4.35 4.91 6.73 6.03
#> 2 B 7.97 7.56 8.27 8.00 6.86 5.52 8.06 4.06 6.69 7.86
#> 3 C 9.07 9.92 10.7 8.64 9.78 9.10 10.5 9.16 9.86 11.1
#desired output
my_tibble %>% do.call(rbind, .) %>% as.tibble() %>% mutate(sample=c("A", "B", "C")) %>% select(sample, everything())
#> # A tibble: 3 x 11
#> sample a b c d e f g h i j
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 A 6.52 4.31 6.11 5.12 4.26 5.68 4.35 4.91 6.73 6.03
#> 2 B 7.97 7.56 8.27 8.00 6.86 5.52 8.06 4.06 6.69 7.86
#> 3 C 9.07 9.92 10.7 8.64 9.78 9.10 10.5 9.16 9.86 11.1
由reprex package(v0.2.0)创建于2018-06-12。
答案 0 :(得分:2)
list
元素名为vector
s。
我们将其转换为tibble
,然后执行bind_rows
或使用map_df
my_tibble %>%
map_df(~ as.list(.x) %>%
as_tibble)
# A tibble: 3 x 10
# a b c d e f g h i j
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 7.40 4.96 5.69 5.03 4.26 5.19 3.20 6.47 5.15 7.17
#2 7.48 6.29 7.61 6.07 5.75 7.29 6.56 7.00 7.07 6.41
#3 9.43 9.86 11.2 8.48 10.6 10.3 11.1 9.70 10.4 10.3
或data.frame
(as.data.frame.list
)
my_tibble %>%
map_df(as.data.frame.list)
# a b c d e f g h
#1 7.401618 4.960760 5.689739 5.028002 4.256727 5.188792 3.195041 6.465555
#2 7.475510 6.290054 7.610726 6.065902 5.746367 7.291446 6.556708 7.001105
#3 9.431331 9.864821 11.178087 8.476433 10.593946 10.332950 11.063100 9.695816
# i j
#1 5.153253 7.172612
#2 7.074341 6.410479
#3 10.370019 10.267099
关于第一个问题,我们可以在map
中使用mutate
,然后在pull
列中使用
tibble(group=c("A", "B", "C"), n_seqs=c(5,7,10)) %>%
mutate(new_col = map(n_seqs, ~ as.list(rnorm(.x, n = 10)) %>%
set_names(letters[1:10]))) %>%
pull(new_col) %>%
bind_rows
# A tibble: 3 x 10
# a b c d e f g h i j
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 5.45 4.98 4.68 4.07 3.51 3.92 6.00 4.38 3.62 6.87
#2 7.43 6.76 8.06 7.89 6.38 9.21 6.74 5.58 6.86 7.21
#3 12.3 10.1 10.5 9.92 9.67 9.97 10.8 12.1 11.0 11.2
根据评论,如果我们还需要'group'列
tibble(group= c("A", "B", "C"), n_seqs = c(5, 7, 10)) %>%
nest(-group) %>%
mutate(new_col = map(data, ~
.x %>%
pull(n_seqs) %>%
rnorm(., n = 10 ) %>%
set_names(letters[1:10]) %>%
as.list %>%
as_tibble)) %>%
select(-data) %>%
unnest
# A tibble: 3 x 11
# group a b c d e f g h i j
# <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 A 6.77 5.34 4.38 4.56 4.49 5.19 5.18 5.92 5.32 4.63
#2 B 6.06 7.63 6.94 7.18 8.10 8.75 6.05 8.64 6.13 7.27
#3 C 10.2 9.72 11.4 9.34 10.7 9.99 9.07 11.2 7.91 9.47
注意:值不同,因为我们没有设置种子
答案 1 :(得分:1)
为什么我必须执行pull并且不能在map函数中指定n_seqs
与mutate
或summarize
不同,map
适用于列表和向量,因此无法从数据框中推断出列。
是否有办法为列表中的各个条目命名 我可以使用map_dfr或bind_rows
请参阅@ akrun的回答,您需要在使用bind_rows
或map_df
之前将每个单独的向量转换为列表。
什么是最好的dplyr / purrr方法才能获得理想的结果?
尝试从sapply
开始,将结果简化为矩阵而不是map
,您可以在以后方便地将其转换为数据框。这只是baseR中的一个:
df <- tibble(group=c("A", "B", "C"), n_seqs=c(5,7,10))
sapply(df$n_seqs, rnorm, n=10) %>%
t %>% as.data.frame %>%
setNames(letters[1:10])
# A tibble: 3 x 10
# a b c d e f g h i j
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 4.93 4.99 3.64 4.19 4.84 3.15 3.81 5.87 2.25 5.80
#2 6.34 5.30 7.56 5.73 6.84 7.30 6.84 7.91 6.60 6.36
#3 9.42 9.28 8.46 10.6 9.73 9.39 10.2 10.8 10.2 9.30