提问人:dan 提问时间:11/9/2023 最后编辑:Phildan 更新时间:11/10/2023 访问量:48
对多个 data.frames 执行循环,以接收包含不同 data.frames 值的表
Do a loop for multiple data.frames to receive a table with values from differen data.frames
问:
我需要为多个 data.frame 循环整个代码。现在这是 CEPSird2,但我也需要它来用于 CEPSird1、CEPSird3、...和其他人(见下文以获取数据)
我想得到的是:我有一个 data.frame(即 CEPSird2),我对“ird2”列感兴趣(其他 data.frames 的列是相等的,并且具有从 2015 年到 2022 年的多年值,但我只需要 >2018)。在第一个循环中,我创建了一个新的 data.frame (ÄnderungAbsolut),其中包含两年之间的绝对差异(“19/20”、“20/21”、“21/22”)。然后,我将这 3 列中的每一列拆分为只有正值和负值,并接收 6 个向量(正 20、正 21、负 20,....),每年两个。之后,我想为这 6 个向量中的每一个计算不同的数字(平均值、sd、基尼和函数 (x)),并将它们汇总到一个表格中(结果)。3X9 表现在是 3 年(“19/20”、“20/21”、“21/22”)和我感兴趣的 8 个数字。现在我需要同样的表,只是不是用于 CEPSird2 中的 ird2,而是用于 CEPSird1 和 ird3 inn CEPSird3 等中的 ird1。如果行前面有年份,而不是像现在这样有 1、2、3 年,以及它们来自哪里(ird2、ord、ird3 等),那就太好了
我知道这很多,但也许有人可以帮助我。多谢。
Test <- data.frame(year= rep(c(2018,2019,2020,2021,2022),6),
id_zewo= rep(c(1:6),each=5),
ird2=runif(30, min = 10000, max = 30000))
Test.id_zewo <- as.numeric(Test[Test$year==2019, c("id_zewo")])
result <- c()
for (i in Test.id_zewo) {
value <- Test %>%
filter(id_zewo %in% i, year > 2018) %>%
select(3)
Wert1 <- value$ird2[2]-value$ird2[1]
Wert2 <- value$ird2[3]-value$ird2[2]
Wert3 <- value$ird2[4]-value$ird2[3]
result <- rbind(result, c(i,Wert1,Wert2,Wert3))
}
ÄnderungAbsolut <- as_tibble(result)
colnames(ÄnderungAbsolut) <- c("id_zewo","19/20","20/21","21/22")
positive20 <- ÄnderungAbsolut[ÄnderungAbsolut$`19/20`>0, ]
positive20 <- positive20[order(positive20$`19/20`, decreasing = TRUE), c("id_zewo","19/20")]
positive21 <- ÄnderungAbsolut[ÄnderungAbsolut$`20/21`>0, ]
positive21 <- positive21[order(positive21$`20/21`, decreasing = TRUE), c("id_zewo","20/21")]
positive22 <- ÄnderungAbsolut[ÄnderungAbsolut$`21/22`>0, ]
positive22 <- positive22[order(positive22$`21/22`, decreasing = TRUE), c("id_zewo","21/22")]
negative20 <- ÄnderungAbsolut[ÄnderungAbsolut$`19/20`<0, ]
negative20 <- negative20[order(negative20$`19/20`), c("id_zewo","19/20")]
negative21 <- ÄnderungAbsolut[ÄnderungAbsolut$`20/21`<0, ]
negative21 <- negative21[order(negative21$`20/21`), c("id_zewo","20/21")]
negative22 <- ÄnderungAbsolut[ÄnderungAbsolut$`21/22`<0, ]
negative22 <- negative22[order(negative22$`21/22`), c("id_zewo","21/22")]
df_listpos <- list(positive20,positive21,positive22)
df_listneg <- list(negative20,negative21,negative22)
extracted_pos <- lapply(df_listpos, purrr::pluck, 2)
extracted_neg <- lapply(df_listneg, purrr::pluck, 2)
mean_pos <- lapply(extracted_pos, mean) |> unlist()
mean_neg <- lapply(extracted_neg, mean) |> unlist()
sd_pos <- lapply(extracted_pos, sd) |> unlist()
sd_neg <- lapply(extracted_neg, sd) |> unlist()
gini_pos <- lapply(extracted_pos, Gini) |> unlist()
gini_neg <- lapply(extracted_neg, Gini) |> unlist()
cumsum_pos <- lapply(extracted_pos, function(x) sum(cumsum(x)/sum(x)<0.75)) |> unlist()
cumsum_neg <- lapply(extracted_neg, function(x) sum(cumsum(x)/sum(x)<0.75)) |> unlist()
results <- data.frame(id = 1:length(extracted_pos), mean_pos, mean_neg, sd_pos, sd_neg,
gini_pos,gini_neg, cumsum_pos,cumsum_neg)
这是我数据的尾巴。年份范围从 2015 年到 2022 年,id_zewo 只是行中值的相应数字。我过滤掉 ird2,因为 CEPSird2,CEPSird3,...还有其他我现在不需要的变量。如果它能简化代码,我已经可以使用我需要的 3 个变量(“year”、“id_zewo”、“ird2”)来保护 CEPSird2,这样我就可以跳过这一步。 例如,ÄnderungAbsolut data.frame 给了我 id_zewo 500 在 19/20、20/21 和 21/22 之间的差异。
tail(CEPSird2[c("year","id_zewo","ird2","ird3")])
year id_zewo ird2 ird3
3859 2022 500 129302 802312
3861 2022 502 4399508 4658553
3867 2022 514 871262 0
3869 2022 518 86635 0
3871 2022 521 128275 0
3872 2022 522 0 0
答:
一种通用方法,用于将相同的操作应用于数据帧列表并合并结果。 并成为您的数据帧:d1
d2
library(dplyr)
d1 <- data.frame(year = 2018, value = rnorm(3), dummy_a = 'junk')
d2 <- data.frame(year = 2019, value = rnorm(3), dummy_b = 'other junk')
list(d1, d2) %>%
Map(f = \(d){## some data processing, e. g.: tidyverse stuff
d %>%
select(year, value) %>%
mutate(value = value * pi)
}) %>%
do.call(rbind, .)
输出:
## year value
## 1 2018 3.2673407
## 2 2018 -1.0875516
## 3 2018 0.2297448
## 4 2019 -1.6449955
## 5 2019 -0.4552625
## 6 2019 -3.8103155
评论
list(d1, d2) %>%
Map
(或 {purrr} 的增强版本将函数应用于列表的每个元素,并返回作项的列表。在上述情况下,列表项是并且仍然是数据帧,然后出于性能原因使用这些数据帧进行组合。在上述情况下,其中的有效负载是一组示例性的 {dplyr} 表达式。map
do.call(rbind, list_of_dataframes)
Map(...)
\(d)
\(x) ...
function(x) ...
我将您的计算重写为代码。由于它的功能,避免了很多循环。简而言之,这使我们能够计算单独的汇总统计数据,例如每个 或每个 .这使我们能够跳过繁琐的创建许多小型中间数据帧。dplyr
for
group_by
year
id
这是整个代码。
所有计算都包含在零件中。请参阅下面的代码细分。
将这些计算应用于许多数据框需要其他所有条件。data_wrangling
library(dplyr)
# create example data frames
test1 <- data.frame(year = rep(c(2018:2022), 6),
id_zewo = rep(c(1:6),each = 5),
ird1 = runif(30, min = 10000, max = 30000))
test2 <- data.frame(year = rep(c(2018:2022), 6),
id_zewo = rep(c(1:6), each = 5),
ird2 = runif(30, min = 100, max = 1000))
test3 <- data.frame(year = rep(c(2018:2022),6),
id_zewo = rep(c(1:6), each = 5),
ird3 = runif(30, min = 1, max = 100))
# create a list containing these data frames
df_list <- list(test1, test2, test3)
# one way to save some hassle is to rename
# all `ird1, 2, 3... ` columns to "value".
# get old colnames
new_colnames <- names(test1)
# inject colname "value" instead of "ird..."
new_colnames[3] <- "value"
# apply column renaming to all data frames
df_list <- lapply(df_list, setNames, new_colnames)
# data wrangling starts
# defining a function that does all the work
# to be called later inside `lapply()`
data_wrangling <- function(x){
x |>
group_by(id_zewo) |>
filter(year > 2018) |>
mutate(year_diff = value - dplyr::lag(value)) |>
ungroup() |>
mutate(positive_diff = year_diff > 0) |> # This is a helper, allowing us to use group by
group_by(positive_diff, year) |>
summarise(mean = mean(year_diff),
sd = sd(year_diff),
n_below_3rd_quartile = sum(cumsum(year_diff) / sum(year_diff) < 0.75))
#gini = Gini(year_diff)) # I dont know what package Gini is from
}
# apply data wrangling steps to all data frames
results <- lapply(df_list, data_wrangling)
# show results
results
结果
每个输入的数据框包含一个结果表的列表。
# [[1]]
# # A tibble: 7 × 5
# # Groups: positive_diff [3]
# positive_diff year mean sd n_below_3rd_quartile
# <lgl> <int> <dbl> <dbl> <int>
# 1 FALSE 2020 -9098. 5046. 2
# 2 FALSE 2021 -5562. 3180. 3
# 3 FALSE 2022 -6050. 4858. 2
# 4 TRUE 2020 7869. 4573. 2
# 5 TRUE 2021 1950. 1915. 0
# 6 TRUE 2022 6578. 6156. 1
# 7 NA 2019 NA NA NA
#
# [[2]]
# # A tibble: 7 × 5
# # Groups: positive_diff [3]
# positive_diff year mean sd n_below_3rd_quartile
# <lgl> <int> <dbl> <dbl> <int>
# 1 FALSE 2020 -150. 157. 1
# 2 FALSE 2021 -348. 297. 2
# 3 FALSE 2022 -36.5 NA 0
# 4 TRUE 2020 596. 194. 2
# 5 TRUE 2021 246. 40.5 1
# 6 TRUE 2022 234. 145. 3
# 7 NA 2019 NA NA NA
#
# [[3]]
# # A tibble: 7 × 5
# # Groups: positive_diff [3]
# positive_diff year mean sd n_below_3rd_quartile
# <lgl> <int> <dbl> <dbl> <int>
# 1 FALSE 2020 -9.30 5.64 1
# 2 FALSE 2021 -18.5 15.2 2
# 3 FALSE 2022 -50.4 15.1 3
# 4 TRUE 2020 21.0 29.8 0
# 5 TRUE 2021 13.5 12.6 2
# 6 TRUE 2022 47.1 9.07 1
# 7 NA 2019 NA NA NA
数据整理部分
让我们看看在自定义数据整理函数中做了什么。让我们以数据为例。test1
test1 |>
group_by(id_zewo) |>
filter(year > 2018) |>
mutate(year_diff = ird1 - dplyr::lag(ird1)) |>
ungroup() |>
mutate(positive_diff = year_diff > 0) |> # This is a helper, allowing us to use group by
group_by(positive_diff, year) |>
summarise(mean = mean(year_diff),
sd = sd(year_diff),
n_below_3rd_quartile = sum(cumsum(year_diff) / sum(year_diff) < 0.75))
#gini = Gini(year_diff)) # I dont know what package Gini is from
这是一个分步总结。
group_by(id_zewo)
正在按 ID 对数据进行分组。这样可以确保以后为每个 id 单独计算 (您尝试在代码开头使用循环实现的目标)。diff
for
筛选数据以排除 2019 年以下的年份
创建一个包含与上一年的差异的列。因为我们分组的依据是 ,所以这个差异是为每个 单独计算的。
diff
ird
id
id_zewo
以下是此步骤中表格的样子:
test1 |>
group_by(id_zewo) |>
filter(year > 2018) |>
mutate(year_diff = ird1 - dplyr::lag(ird1))
# Output:
# A tibble: 24 × 4
# Groups: id_zewo [6]
# year id_zewo ird1 year_diff
# <int> <int> <dbl> <dbl>
# 2019 1 23248. NA
# 2020 1 19966. -3282.
# 2021 1 23271. 3304.
# 2022 1 21833. -1437.
# 2019 2 28372. NA
# 2020 2 16062. -12310.
# 2021 2 10383. -5678.
# 2022 2 23761. 13378.
# 2019 3 19182. NA
# 2020 3 27070. 7887.
请注意,我们的分组是有效的,因为在每个组中,差异都以 2019 年开始,因为 2019 年之前没有年份。id
NA
year
删除分组
我们这样做是因为以下汇总统计数据应由 而不是由 计算。我们想要 2019 年、2020 年等。但首先我们需要创建一个帮助程序列。
year
id
mean
创建一个帮助程序列,指示差异是否为正值。
year_diff
按此帮助程序列和 进行分组,以便我们在后续步骤中获取每个单独年份的汇总统计信息,并分别获取正差异和负差异的汇总统计信息。
positive_diff
year
计算汇总统计数据。您可以调整代码以包含我没有找到的函数。
Gini
数据整理输出test1
# # A tibble: 7 × 5
# # Groups: positive_diff [3]
# positive_diff year mean sd n_below_3rd_quartile
# <lgl> <int> <dbl> <dbl> <int>
# 1 FALSE 2020 -9098. 5046. 2
# 2 FALSE 2021 -5562. 3180. 3
# 3 FALSE 2022 -6050. 4858. 2
# 4 TRUE 2020 7869. 4573. 2
# 5 TRUE 2021 1950. 1915. 0
# 6 TRUE 2022 6578. 6156. 1
# 7 NA 2019 NA NA NA
如何阅读此输出:
- 正差异的汇总统计信息位于列中
TRUE
positive_diff
- 负差异的统计信息在行中,其中 是 。
positive_diff
FALSE
- 最后一行可以忽略。它之所以在这里,是因为认为它本身就是一个群体。
NA
group_by(positive_diff)
NA
评论
CEPSird2
CEPS
dput(head(CEPS))
ird
NA
NA
CEPS