Использование значения столбца в качестве индекса кадра данных в кадрах данных списка (карта или сопоставление с seq_along)? - PullRequest
1 голос
/ 29 мая 2020

У меня есть список фреймов данных list1, и мне нужен новый столбец mn в каждом фрейме данных, который является средним условным числом столбцов на основе значения в другом столбце num плюс один. Итак, для num=3 новый столбец будет средним из первых четырех столбцов. В приведенном ниже примере

df1 <- data.frame(num= c(3, 1, 1, 1, 2), d1= c(1, 17, 17, 17, 15), d2= c(1, 15, 15, 15, 21), d3= c(6, 21, 21, 21, 23), d4= c(2, 3, 3, 3, 2))
df2 <- data.frame(num= c(3, 2, 2, 2, 2), d1= c(1, 10, 10, 10, 15), d2= c(1, 5, 5, 5, 21), d3= c(6, 2, 2, 2, 23), d4= c(2, 3, 3, 3, 5))
list1 <- list(df1, df2)

я ожидал бы

newlist
[[1]]
   num   d1   d2   d3   d4    mn
1   3    1    1    6    2    2.5
2   1    17   15   21   3    16.0  
3   1    17   15   21   3    16.0 

Ближайшее, что я получил, это

newlist <- lapply(list1, function(x) {
  x <- cbind(x, sapply(x$num, function(y) {
      y <- rowSums(x[2:(2+y)])/(y+1)
      }))
  })

, который связывает столбцы для средних значений каждой строки . На основании этого сообщения Я думаю, мне нужен seq_along или, может быть, карта внутри функции, но я не могу понять, как это реализовать.

1 Ответ

1 голос
/ 29 мая 2020

Можно использовать l oop вместо list с lapply, извлечь количество элементов для каждой строки с помощью apply на основе значения столбца 'num' (+1), получить mean и создайте новый столбец в transform

lapply(list1, function(x)  transform(x,
       mn = apply(x, 1, function(y) mean(y[-1][seq(y[1]+1)]))))
#[[1]]
#  num d1 d2 d3 d4       mn
#1   3  1  1  6  2  2.50000
#2   1 17 15 21  3 16.00000
#3   1 17 15 21  3 16.00000
#4   1 17 15 21  3 16.00000
#5   2 15 21 23  2 19.66667

#[[2]]
#  num d1 d2 d3 d4        mn
#1   3  1  1  6  2  2.500000
#2   2 10  5  2  3  5.666667
#3   2 10  5  2  3  5.666667
#4   2 10  5  2  3  5.666667
#5   2 15 21 23  5 19.666667

Или с tidyverse, перейдя в «длинный» формат с помощью pivot_longer, выполните группировку по строкам и получите mean первых n элементов на основе значения num

library(purrr)
library(dplyr)
library(tidyr)
map(list1, ~
        .x %>% 
           mutate(rn = row_number()) %>%
           pivot_longer(cols = starts_with('d')) %>% 
           group_by(rn) %>% 
           summarise(value = mean(value[seq_len(first(num) + 1)])) %>%
           pull(value) %>%
           bind_cols(.x, mn = .))
...