提问人:Luther_Proton 提问时间:7/4/2022 更新时间:7/4/2022 访问量:128
在 R 中通过多个 Dataframe 循环管道运算符代码
Looping pipe operator code through multiple Dataframe in R
问:
有谁知道如何通过多个数据帧循环管道运算符代码?
多年来,我命名了不少数据帧(df_1990、df_1991......df_2020)。但是,并非所有年份都包括在内(即 df_1993 年、df_2012 年和 3 年以上不可用)。为了解决这个问题,我手动创建了一个列表来存储循环的所有数据帧(如果有更快的方法,请告诉我)。
df_list = list(df_1990, df_1991, ..., df_2020)
for (i in df_list) {
...
}
数据帧非常简单,只有 2 列(Item(字符字段)和 Cost(数字字段)。
项目 | 成本 |
---|---|
Book_A | 3.00 |
Book_B | 5.00 |
... | ... |
DataFrame 的示例代码
df = structure(list(Item = structure(c(1L, 1L, 1L, 2L, 2L, 3L, 2L,
3L, 1L, 2L, 1L, 2L, 1L, 3L, 1L, 2L, 2L, 1L, 3L, 1L), .Label = c("Book A",
"Book B", "Book C"), class = "factor"), Cost = c(5, 3.5, 12,
6, 8, 3, 6, 3.5, 3.8, 13, 5.1, 7, 11.5, 3.8, 5.5, 6.5, 13.5,
5.5, 3.5, 1.2)), class = "data.frame", row.names = c(NA, -20L
))
有谁知道我如何将以下代码添加到...上面的 for 循环代码的一部分?谢谢!
df %>%
group_by(Item) %>%
summarise(outlier = mean(Cost),
offset = outlier * 0.6,
higher_value = outlier + offset,
lower_value = outlier - offset) %>%
left_join(df, by = 'Item') %>%
transmute(Item, Cost, Outlier = ifelse(Cost < lower_value | Cost > higher_value, 'Y', 'N'))
该代码基本上检测异常值(例如,如果成本比特定项目的大多数平均值高或低 60%),并为每行分别输出一列“Y”和“N”。(代码的功劳归 Ronak Shah 所有)
理想情况下,创建的新列应出现在创建的列表中,以允许导出为 excel 格式
谢谢!
答:
2赞
stefan
7/4/2022
#1
就我个人而言,我会在函数中移动数据整理代码,然后用于遍历数据帧列表。lapply
library(dplyr)
df_list <- list(df, df, df)
prep_data <- function(x) {
x %>%
group_by(Item) %>%
summarise(
outlier = mean(Cost),
offset = outlier * 0.6,
higher_value = outlier + offset,
lower_value = outlier - offset
) %>%
left_join(x, by = "Item") %>%
transmute(Item, Cost, Outlier = ifelse(Cost < lower_value | Cost > higher_value, "Y", "N"))
}
df_prep <- lapply(df_list, prep_data)
lapply(df_prep, head, 2)
#> [[1]]
#> # A tibble: 2 × 3
#> Item Cost Outlier
#> <fct> <dbl> <chr>
#> 1 Book A 5 N
#> 2 Book A 3.5 N
#>
#> [[2]]
#> # A tibble: 2 × 3
#> Item Cost Outlier
#> <fct> <dbl> <chr>
#> 1 Book A 5 N
#> 2 Book A 3.5 N
#>
#> [[3]]
#> # A tibble: 2 × 3
#> Item Cost Outlier
#> <fct> <dbl> <chr>
#> 1 Book A 5 N
#> 2 Book A 3.5 N
如果你想通过循环来做到这一点,那么你可以得到同样的结果,如下所示:for
df_prep <- list()
for (i in seq_along(df_list)) {
df_prep[[i]] <- prep_data(df_list[[i]])
}
1赞
MarkusN
7/4/2022
#2
为什么不将所有数据放入一个数据帧中:
df_list = list(df_1990 = df_1990, df_1991 = df_1991, ..., df_2020 = df_2020)
df2 = dplyr::bind_rows(df_list, .id = 'Year')
然后,您只需将变量添加到语句中:Year
group_by
group_by(Year, Item)
如果需要,可以随时将其转换回数据帧列表:
df2 %>%
tidyr::nest(data = Item:Cost) %>%
pull(data, name = Year)
顺便说一句,您还可以通过省略连接来改进异常值检测的代码:
df2 %>%
group_by(Year, Item) %>%
mutate(outlier = mean(Cost),
offset = outlier * 0.6,
higher_value = outlier + offset,
lower_value = outlier - offset) %>%
transmute(Item, Cost, Outlier = if_else(Cost < lower_value | Cost > higher_value, 'Y', 'N'))
使用 而不是将结果复制到组的每一行。mutate
summarise
mean(Cost)
评论
0赞
Luther_Proton
7/4/2022
也感谢您对异常值检测代码的改进!
评论
library(dplyr)