将数据框转换为列表,具有应用系列的功能

Convert data frame to a list, with function from apply family

如标题所示,我需要转换一些数据框

data1 <- data.frame(Year = rep(c(2016, 2017, 2018, 2019), each = 12), Month = rep(month.abb, 4), Expenses = sample(50e3:100e3, 48))

创建一个列表year_y,其中每年(元素)包含一个数据框,每个月都有费用。然后使用 list year_y 创建一个列表,其中包含每年(元素)费用最高的月份。最终结果应该是这样的:

$‘2016‘
[1] "Jul"

$‘2017‘
[1] "Nov"

$‘2018‘
[1] "May"

$‘2018‘
[1] "May"

问题是我需要在这两个步骤中使用应用函数族

我们按 'Year'、slice 'Expenses' 是 max 的行分组,然后 split 'Month' 按 'Year'列

library(dplyr)
data1 %>%
    group_by(Year) %>% 
    slice_max(n = 1, order_by = Expenses) %>%
    {split(.$Month, .$Year)}

或者另一种选择是 deframe

library(tibble)
data1 %>%
   group_by(Year) %>% 
   slice_max(n = 1, order_by = Expenses) %>%
   ungroup %>% 
   select(Year, Month) %>% 
   deframe() %>%
   as.list
$`2016`
[1] "Nov"

$`2017`
[1] "Dec"

$`2018`
[1] "Dec"

$`2019`
[1] "Mar"

或使用 base R - subset 数据,其中 'Expenses' 是 max 值且 split

with(subset(data1, Expenses == ave(Expenses, Year, FUN = max)), 
      split(Month, Year))

-输出

$`2016`
[1] "Nov"

$`2017`
[1] "Dec"

$`2018`
[1] "Dec"

$`2019`
[1] "Mar"

使用基础 R。 使用 split() 函数将原始数据框按年份划分。然后用which.max()判断哪个月的费用最高。

data1 <- data.frame(Year = rep(c(2016, 2017, 2018, 2019), each = 12), Month = rep(month.abb, 4), Expenses = sample(50e3:100e3, 48))

lapply(split(data1, ~Year), function(mon) {
   mon$Month[which.max(mon$Expenses)]
})

在基础 R 中,我们可以使用 tapply

as.list(tapply(ata1$Expenses, ata1$Year, function(x) month.abb[which.max(x)]))
#> $`2016`
#> [1] "Jul"
#> 
#> $`2017`
#> [1] "Mar"
#>
#> $`2018`
#> [1] "Sep"
#> 
#> $`2019`
#> [1] "Dec"

这是另一种使用 dplyr::pulls name 参数的 tidyverse 方法。

library(dplyr)

data1 %>% 
  group_by(Year) %>% 
  filter(max(Expenses) == Expenses) %>% 
  pull(var = Month, name = Year) %>% 
  as.list()

#> $`2016`
#> [1] "Feb"
#> 
#> $`2017`
#> [1] "Apr"
#> 
#> $`2018`
#> [1] "Mar"
#> 
#> $`2019`
#> [1] "Dec"

reprex package (v0.3.0)

于 2022-03-26 创建

这是使用 purrr map_chr 的另一种解决方案:

library(purrr)
library(dplyr)

data1 %>% 
  group_by(Year) %>% 
  arrange(desc(Expenses), .by_group = TRUE) %>% 
  slice(1) %>% 
  group_split() %>% 
  setNames(unique(data1$Year)) %>% 
  map_chr(., 2) %>% 
  as.list()
$`2016`
[1] "Apr"

$`2017`
[1] "Jan"

$`2018`
[1] "Mar"

$`2019`
[1] "Nov"