R: разбить фрейм данных на список по группам и итерациям строк

#r #list #split

#r #Список #разделить

Вопрос:

У меня есть фрейм данных следующим образом:

 set.seed(34)
startingframe <-  data.frame(
  group1=factor(rep(c("a","b"),each=3,times=1)),
  time=rep(1:3,each=1,times=2),
  othercolumn=rnorm(1:6)
)
  

… который я пытаюсь преобразовать в список, который разбивается по группам и каждой «итерации» time столбца, результаты выглядят так:

  $a1
  group1 time othercolumn
1      a    1    -0.13889

$a2
  group1 time othercolumn
1      a    1   -0.138890
2      a    2    1.199813

$a3
  group1 time othercolumn
1      a    1  -0.1388900
2      a    2   1.1998129
3      a    3  -0.7477224

$b1
  group1 time othercolumn
4      b    1  -0.5752482

$b2
  group1 time othercolumn
4      b    1  -0.5752482
5      b    2  -0.2635815

$b3
  group1 time othercolumn
4      b    1  -0.5752482
5      b    2  -0.2635815
6      b    3  -0.4554921
  

Я думаю, мне просто нужен бит итерации, встроенный в этот код:

 split_list <- split(startingframe,list(startingframe$group1,startingframe$time))
  

РЕДАКТИРОВАТЬ: возможно, я слишком упростил исходную проблему, но в реальном наборе данных есть дополнительные столбцы, которые необходимо было бы перенести в список.

Ответ №1:

Вы можете использовать head для каждого числа в последовательности 1:nrow(x) , для каждой подгруппы x ваших данных

 out <- lapply(split(df, df$group1), function(x) lapply(1:nrow(x), head, x = x))
out <- unlist(out, recursive = F)

out
# $`a1`
#    group1 time
# 1:      a    1
# 
# $a2
#    group1 time
# 1:      a    1
# 2:      a    2
# 
# $a3
#    group1 time
# 1:      a    1
# 2:      a    2
# 3:      a    3
# 
# $b1
#    group1 time
# 1:      b    1
# 
# $b2
#    group1 time
# 1:      b    1
# 2:      b    2
# 
# $b3
#    group1 time
# 1:      b    1
# 2:      b    2
# 3:      b    3
  

Возможно, вам не нужно создавать список всех этих фреймов данных, вы можете просто создать список индексов и использовать их по мере необходимости.

 inds <- 
  lapply(split(seq(nrow(df)), df$group1), function(x) 
    lapply(1:length(x), function(y) x[seq(y)]))

inds
# $`a`
# $`a`[[1]]
# [1] 1
# 
# $`a`[[2]]
# [1] 1 2
# 
# $`a`[[3]]
# [1] 1 2 3
# 
# 
# $b
# $b[[1]]
# [1] 4
# 
# $b[[2]]
# [1] 4 5
# 
# $b[[3]]
# [1] 4 5 6

df[inds$b[[2]]]
#    group1 time
# 1:      b    1
# 2:      b    2
  

Комментарии:

1. Я думаю, проблема здесь в том, что он создает список списков?

2. Вы можете использовать unlist его, если хотите, как единый список фреймов данных. Я отредактировал ответ.

Ответ №2:

Здесь не разделение, а генерация желаемого результата.

 genlist = function(l,t){return((data.frame(group1=rep(x = l,times=t),time=seq(from=1,to = t,by = 1))))}

mapply(genlist,startingframe$group1,startingframe$time,SIMPLIFY = FALSE)
  

Комментарии:

1. Есть ли способ, которым это сработало бы, если бы мы хотели добавить дополнительные столбцы в таблицу?

Ответ №3:

Одним из способов сделать это было бы использование lapply внутри другого lapply

 lapply(levels(startingframe$group1), function(group) {
  df = startingframe[startingframe$group1 == group, ]
  lapply(df$time, function(time) {
    df[df$time %in% 1:time, ]
  })
})

[[1]]
[[1]][[1]]
  group1 time
1      a    1

[[1]][[2]]
  group1 time
1      a    1
2      a    2

[[1]][[3]]
  group1 time
1      a    1
2      a    2
3      a    3


[[2]]
[[2]][[1]]
  group1 time
4      b    1

[[2]][[2]]
  group1 time
4      b    1
5      b    2

[[2]][[3]]
  group1 time
4      b    1
5      b    2
6      b    3