【问题标题】:How to create a for loop for combining several data frames and df subsets into one data frame?如何创建一个用于将多个数据帧和 df 子集组合成一个数据帧的 for 循环?
【发布时间】:2019-12-19 09:32:58
【问题描述】:

我正在尝试修改数据框并努力将我的操作组合到一个 for 循环中。我想根据一个特定的列对数据框进行子集化,将不同的行附加到每个子集,然后将修改后的子集再次组合成一个数据框。我们以虹膜数据为例:

#Create data frame subsets based on Species column
iris_subs <- split(iris, iris$Species)

#create an empty data frame with the same columns as in iris and one empty row
emptydf <- iris[FALSE,]
emptydf[nrow(emptydf)+1,] <- NA

#create a data frame with sums for each species
iris %>% group_by(Species) %>% summarise_all(sum) -> iris_sums
iris_sums <- iris_sums[,-c(1)] #delete column with species names

#Combine data frames into one data frame with original data, sum for this species and an empty row for each subset
iris_setosa <- bind_rows(iris_subs[1], iris_sums[1,], emptydf)
iris_versicolor <- bind_rows(iris_subs[2], iris_sums[2,], emptydf)
iris_virginica <- bind_rows(iris_subs[3], iris_sums[3,], emptydf)
new_iris <- bind_rows(iris_setosa, iris_versicolor, iris_virginica)

这段代码完成了这项工作。但是,我想以这种方式处理数百个数据帧,并且每个数据帧的不同物种的数量各不相同。如何自动化 for 循环中的最后一部分?

我想要这样的东西

#empty data frame to store output
new_iris <- iris[FALSE,]    

for (i in iris_subs) {
        new_iris[i] <- bind_rows(iris_subs[i], iris_sums[i,], emptydf)
        new_iris <- merge(new_iris[i])
    }

Error in iris_subs[i] : invalid subscript type 'list'

除了错误之外,这可能太简单了……我是 R 初学者,已经在网上搜索了好几天,但找不到任何答案。有没有人对如何实现这一目标提出建议?感谢您的任何提示!

【问题讨论】:

    标签: r dataframe for-loop


    【解决方案1】:

    我们可以创建一个函数并为所有数据帧重复它。这是您尝试做的简短版本

    library(dplyr)
    
    repeat_process <- function(df) {
       iris_sums <- df %>% group_by(Species) %>% summarise_all(sum) %>% select(-Species)
       df %>% bind_rows(iris_sums, emptydf[rep(1:nrow(emptydf), n_distinct(df$Species)), ])
    }
    

    现在假设您有一个数据框列表

    list_df <- list(iris, iris)
    

    您可以将此函数应用于列表中的每个数据框

    lapply(list_df, repeat_process)
    

    【讨论】:

    • 感谢您的回答!但是,这会将总和和空行附加到最终数据帧的末尾,而不是在每个物种子集之后。你知道如何解决这个问题吗?
    【解决方案2】:

    您可以定义一个函数来汇总 data.frame 的所有数字列,并将其他列保留为 NA,将其附加到原始数据框:

    numericCols = sapply(iris,is.numeric)
    
    func = function(df,numCols){
    
    iris_sums <- colSums(df[,numCols])
    result <- rep(NA,ncol(df))
    names(result) <- colnames(df)
    result[names(iris_sums)] <- iris_sums
    rbind(df,result,rep(NA,ncol(df)))
    }
    

    然后我们使用 purrr 来映射每个子集:

    split(iris,iris$Species) %>% map_dfr(func,numCols=numericCols)
    

    【讨论】:

    • 感谢您的回答!这看起来不错,但我在总和和下一个物种之间缺少空行。你知道如何包含它吗?
    • 哦,你需要那个。好的,当然。我认为这不是故意的
    • 这看起来很棒!非常感谢你的帮助! :)
    猜你喜欢
    • 2020-05-01
    • 2019-07-29
    • 1970-01-01
    • 2022-08-06
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    • 1970-01-01
    • 2023-03-19
    相关资源
    最近更新 更多