From list to data frame with tidyverse, selecting specific list elements
We can use imap
and enframe
to convert each element in the list to a data frame with name
(row number) and value
(the element name). We can then use reduce
and full_join
to join all data frames. Finally, we can select the columns we want. This approach does not need to specify a "magic" number.
library(tidyverse)
some_data$x %>%
as.numeric() %>%
hist(breaks = seq(from = 23, to = 24.6, by = 0.2),
plot = FALSE) %>%
imap(~enframe(.x, value = .y)) %>%
reduce(full_join, by = "name") %>%
select(bins = breaks,
frequency = counts)
# # A tibble: 9 x 2
# bins frequency
# <dbl> <int>
# 1 23 3
# 2 23.2 9
# 3 23.4 20
# 4 23.6 23
# 5 23.8 19
# 6 24 16
# 7 24.2 7
# 8 24.4 3
# 9 24.6 NA
Part of the complicating factor is that the lists of a hist()
object have different lengths:
library(tidyverse)
brks <- seq(from = 23, to = 24.6, by = 0.2)
hist_res <- some_data$x %>%
as.numeric() %>%
hist(breaks = brks,
plot = FALSE)
lengths(hist_res)
breaks counts density mids xname equidist
9 8 8 8 1 1
OP commented that uneven lists is a main part of the question. We need to make a choice or rule to determine which list elements are selected for a data.frame
. In this case, we can select the most frequent length using a combination of table()
, which()
, and base [
. For this hist()
example, I still include manually manipulating the breaks
column in a mutate
call:
l <- lengths(hist_res)
cols <- which(l == as.integer(names(table(l)))[which.max(table(l))])
hist_res%>%
.[cols]%>%
as_tibble()%>%
mutate(brk_start = brks[-length(brks)],
brk_end = brks[-1])
# A tibble: 8 x 5
counts density mids brk_start brk_end
<int> <dbl> <dbl> <dbl> <dbl>
1 3 0.15 23.1 23 23.2
2 9 0.45 23.3 23.2 23.4
3 20 1.000 23.5 23.4 23.6
4 23 1.15 23.7 23.6 23.8
5 19 0.95 23.9 23.8 24
6 16 0.8 24.1 24 24.2
7 7 0.35 24.3 24.2 24.4
8 3 0.150 24.5 24.4 24.6