кадр данных из списка векторов - PullRequest
3 голосов
/ 03 августа 2020

У меня есть 4 вектора (d1, d2, d3, d4) разной длины, из которых я создаю такой фрейм данных

df <- data.frame(
  x = c(
    seq_along(d1),
    seq_along(d2),
    seq_along(d3),
    seq_along(d4)
  ),
  y = c(
    d1,
    d2,
    d3,
    d4
  ),
  id = c(
    rep("d1", times = length(d1)), 
    rep("d2", times = length(d2)),
    rep("d3", times = length(d3)),
    rep("d4", times = length(d4))
  ))

Добавление нового вектора означает добавление его в 3 разных местах, это вот чего я бы хотел избежать. В идеале я хотел бы передать d1,d2,d3,d4 в функцию, которая затем возвращает фрейм данных.

Первые шаги, кажется, заключаются в том, чтобы обернуть векторы в список и назвать их.

l <- list(d1,d2,d3,d4)
names(l) <- c("d1","d2","d3","d4")

Но я борюсь со второй частью, которая, вероятно, должна быть чем-то вроде этого (псевдокод)

df <- data.frame(
  x = flatten(map(l, function(a) seq_along(a))),
  y = flatten(l),
  id = flatten(map(l, function(a) rep(a.name,times=length(a))))
)

Как правильно построить фрейм данных из списка? Или есть лучший способ сделать это?

ОБНОВЛЕНИЕ: для демонстрационных целей можно представить d1..d4 как

d1 <- pnorm(seq(-2, 2, 0.05))-3
d2 <- pnorm(seq(-3, 3, 0.10))
d3 <- pnorm(seq(-1, 2, 0.05))-4
d4 <- pnorm(seq(-4, 3, 0.15))

Ответы [ 3 ]

3 голосов
/ 03 августа 2020

Вы можете определить функцию, которая принимает любое количество векторов:

build_df <- function(...)
{
  vec_list <- list(...)
  df <- data.frame(x = do.call("c", sapply(vec_list, seq_along)),
                   y = do.call("c", vec_list),
                   name = do.call("c", sapply(seq_along(vec_list), 
                                              function(i) rep(names(vec_list)[i], 
                                                          length(vec_list[[i]]))))
             )
  rownames(df) <- seq(nrow(df))
  df
}

build_df(d1 = 1:3, d2 = 6:9, bananas = 4:6)
#>    x y    name
#> 1  1 1      d1
#> 2  2 2      d1
#> 3  3 3      d1
#> 4  1 6      d2
#> 5  2 7      d2
#> 6  3 8      d2
#> 7  4 9      d2
#> 8  1 4 bananas
#> 9  2 5 bananas
#> 10 3 6 bananas

Создано 2020-08-03 пакетом REPEX (v0.3.0)

0 голосов
/ 03 августа 2020

Мы могли бы использовать mget

library(dplyr)
library(tibble)
library(tidyr)
library(data.table)
mget(paste0("d", 1:4)) %>% 
   enframe(name = 'id', value = 'y') %>% 
   unnest(c(y)) %>% 
   mutate(x = rowid(id))
0 голосов
/ 03 августа 2020

Ваш y может быть легко собран с unlist. Мне нужен был for l oop для генерации x и id. Как насчет этой функции?

d1 <- pnorm(seq(-2, 2, 0.05))-3
d2 <- pnorm(seq(-3, 3, 0.10))
d3 <- pnorm(seq(-1, 2, 0.05))-4
d4 <- pnorm(seq(-4, 3, 0.15))
my_list <- list(d1 = d1, d2 = d2, d3 = d3, d4 = d4)
 
build_df <- function(list) {
  names <- names(list)
  x <- integer()
  id <- character()
  for(i in 1:length(list)) {
    x <- c(x, seq_along(list[[i]]))
    id <- c(id, rep(names[i], length(list[[i]])))
  }
  y <- unname(unlist(list))
  df <- data.frame(x = x, y = y, id = id)
  return(df)
}
 
df <- build_df(my_list)
head(df)
  x         y id
1 1 -2.977250 d1
2 2 -2.974412 d1
3 3 -2.971283 d1
4 4 -2.967843 d1
5 5 -2.964070 d1
6 6 -2.959941 d1
...