使用lapply按列对数据帧列表进行分组

时间:2019-11-11 23:50:51

标签: r list dataframe group-by lapply

我有一个包含多个数据帧的列表。我想按类别(A)对数据进行排序,并使用B命令对频率(lapply)求和。

数据为df_list

df_list
$`df.1`

        A       B
1   Apples      2
2   Pears       5
3   Apples      6
4   Pears       1
5   Apples      3


$`df.2`
        A       B
1   Oranges     2
2   Pineapples  5
3   Oranges     6
4   Pineapples  1
5   Oranges     3

所需的结果df_list_2看起来像这样:

df_list_2
$`df.1`

        A       B
1   Apples      11
2   Pears       6       

$`df.2`
        A       B
1   Oranges     11
2   Pineapples  6

我已经基于lapply尝试了以下代码:

df_list_2<-df_list[, lapply(B, sum), by = A]

但是,我收到一个错误代码,说找不到A

在这种情况下,我可能会误认为lapply命令的工作方式,或者我对它应该如何工作的轻描淡写存在缺陷。 任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:4)

您需要在aggregate中的lapply

lapply(df_list, function(x) aggregate(B~A, x, sum))

#[[1]]
#       A  B
#1 Apples 11
#2  Pears  6

#[[2]]
#           A  B
#1    Oranges 11
#2 Pineapples  6

使用mappurrr中的dplyr

library(dplyr)
purrr::map(df_list, ~.x %>% group_by(A) %>% summarise(sum = sum(B)))

数据

df_list <- list(structure(list(A = structure(c(1L, 2L, 1L, 2L, 1L), 
.Label = c("Apples", "Pears"), class = "factor"), B = c(2L, 5L, 6L, 1L, 3L)), 
class = "data.frame", row.names = c("1", "2", "3", "4", "5")), 
structure(list(A = structure(c(1L, 2L, 1L, 2L, 1L), .Label = c("Oranges", 
"Pineapples"), class = "factor"), B = c(2L, 5L, 6L, 1L, 3L)), class = "data.frame", 
row.names = c("1", "2", "3", "4", "5")))

答案 1 :(得分:1)

我担心您可能对lapply或提取操作符([)都不了解。请记住,lapply(list, function)将指定的function应用于您赋予的list的每个元素。提取为您提供您指定的元素:

x <- c('a', 'b', 'c')
x[2]
## "b"

我可以想象在R工作区的某个地方有一个对象名B,这就是为什么您不会在

的地方出现错误的原因
## Error in lapply(B, sum) : object 'B' not found

相反,如果您同时(有意或无意)定义了AB,则会看到错误消息

## Error in df_list[, lapply(B, sum), by = A] : incorrect number of dimensions

因为根本就不是[的使用方式;请记住,您只是将索引或布尔值与偶然的可选参数一起传递给[,但是by并不是其中之一。

因此,在没有进一步的前提下,这是我将如何执行此操作(在基数R中):

# make some data
a <- c(1, 2, 1, 2, 1)
b <- c(2, 5, 6, 1, 3)
df_list <- list(df.1 = data.frame(A = c('Apples', 'Pears')[a], B = b), 
                df.2 = data.frame(A = c('Oranges', 'Pineapples')[a], B = b))

# simplify it
df_list_2 <- lapply(df_list, function(x) {
    aggregate(list(B = x$B), list(A = x$A), sum)
})

# the desired result
df_list_2

## $df.1
##        A  B
## 1 Apples 11
## 2  Pears  6
## 
## $df.2
##            A  B
## 1    Oranges 11
## 2 Pineapples  6

您可以利用data.frame只是一个列表这一事实,并缩短代码,如下所示:

df_list_2 <- lapply(df_list, function(x) {
    aggregate(x['B'], x['A'], sum)
})

但是第一种书写方式应该有助于更清楚地了解我们在做什么

答案 2 :(得分:1)

OP帖子中的data.table语法可以更改为

library(data.table)
lapply(df_list, function(x) as.data.table(x)[, .(B = sum(B)), by = A])
#$df.1
#        A  B
#1: Apples 11
#2:  Pears  6

#$df.2
#            A  B
#1:    Oranges 11
#2: Pineapples  6

数据

df_list <- list(df.1 = structure(list(A = structure(c(1L, 2L, 1L, 2L, 1L
), .Label = c("Apples", "Pears"), class = "factor"), B = c(2L, 
5L, 6L, 1L, 3L)), class = "data.frame", row.names = c("1", "2", 
"3", "4", "5")), df.2 = structure(list(A = structure(c(1L, 2L, 
1L, 2L, 1L), .Label = c("Oranges", "Pineapples"), class = "factor"), 
    B = c(2L, 5L, 6L, 1L, 3L)), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5")))