首页 文章

循环遍历子集,获取文件并将结果保存在数据框中

提问于
浏览
0

已经提出了类似的问题,但没有一个能够解决我的具体问题 . 我有一个包含许多基本微积分的 .R 文件("Mycalculus.R"),我需要将其应用于数据框的子集:每年一个子集,其中"year"的模态是因子(yearA,yearB,yearC)而不是数值 . 该文件生成一个新的数据帧,我需要将其保存在Rda文件中 . 这是我希望代码看起来像 for 循环(这显然不起作用):

id <- identif(unlist(df$year))
for (i in 1:length(id)){
    data <- subset(df, year == id[i])
    source ("Mycalculus.R", echo=TRUE)
    save(content_df1,file="myresults.Rda")
}

这是主要data.frame df的精确:

obs    year    income    gender   ageclass    weight
 1     yearA    1000       F         1          10
 2     yearA    1200       M         2          25
 3     yearB    1400       M         2           5
 4     yearB    1350       M         1          11

以下是源文件“Mycalculus.R”的作用:它将大量基本微积分应用于称为“数据”的数据帧列,并根据df1创建两个新的数据帧df1和df2 . 这是一个摘录:

data <- data %>% 
   group_by(gender) %>% 
   mutate(Income_gender = weighted.mean(income, weight))
data <- data %>% 
   group_by(ageclass) %>% 
   mutate(Income_ageclass = weighted.mean(income, weight))

library(GiniWegNeg)
gini=c(Gini_RSV(data$Income_gender, weight), Gini_RSV(data$Income_ageclass,weight))

df1=data.frame(gini)
colnames(df1) <- c("Income_gender","Income_ageclass")
rownames(df1) <- c("content_df1")

df2=(1/5)*df1$Income_gender+df2$Income_ageclass
colnames(df2) <- c("myresult")
rownames(df2) <- c("content_df2")

最后,我得到两个这样的数据帧:

Income_Gender  Income_Ageclass    
content_df1           ....             ....

而对于df2:

myresult      
content_df2           ....

但我需要将df1和Rf2保存为Rda文件,其中每个子集给出content_df1和content_df2的行名称,如下所示:

Income_Gender  Income_Ageclass    
content_df1_yearA     ....             ....     
content_df1_yearB     ....             ....     
content_df1_yearC     ....             ....

myresult
content_df2_yearA     ....   
content_df2_yearB     ....    
content_df2_yearC     ....

目前,我的程序不使用任何循环,并且正在完成工作但是很乱 . 基本上代码超过2500行代码 . (请不要向我扔西红柿) .

有人可以帮我解决这个具体要求吗?先感谢您 .

2 回答

  • 2

    考虑在一个脚本中加入所需参数的定义函数,由 lapply() 调用 . 然后,Lapply返回一个数据帧列表,您可以将其绑定到最后一个df中 .

    library(dplyr)
    library(GiniWegNeg)
    
    runIncomeCalc <- function(data, y){      
      data <- data %>% 
        group_by(gender) %>% 
        mutate(Income_gender = weighted.mean(income, weight))
      data <- data %>% 
        group_by(ageclass) %>% 
        mutate(Income_ageclass = weighted.mean(income, weight))      
    
      gini <- c(Gini_RSV(data$Income_gender, weight), Gini_RSV(data$Income_ageclass,weight))
    
      df1 <- data.frame(gini)
      colnames(df1) <- c("Income_gender","Income_ageclass")
      rownames(df1) <- c(paste0("content_df1_", y))
    
      return(df1)
    }
    
    runResultsCalc <- function(df, y){
      df2 <- (1/5) * df$Income_gender + df$Income_ageclass
      colnames(df2) <- c("myresult")
      rownames(df2) <- c(paste0("content_df2_", y)
    
      return(df2)
    }
    
    dfIncList <- lapply(unique(df$year), function(i) {      
      yeardata <- subset(df, year == i)
      runIncomeCalc(yeardata, i)      
    })
    
    dfResList <- lapply(unique(df$year), function(i) {      
      yeardata <- subset(df, year == i)
      df <- runIncomeCalc(yeardata, i) 
      runResultsCalc(df, i)      
    })
    
    df1 <- do.call(rbind, dfIncList)
    df2 <- do.call(rbind, dfResList)
    

    现在,如果您需要跨脚本来源 . 在Mycalculus.R中创建相同的两个函数runIncomeCalc和runResultsCalc,然后在其他脚本中调用每个函数:

    library(dplyr)
    library(GiniWegNeg)
    
    if(!exists("runIncomeCalc", mode="function")) source("Mycalculus.R")
    
    dfIncList <- lapply(unique(df$year), function(i) {      
      yeardata <- subset(df, year == i)
      runIncomeCalc(yeardata, i)      
    })
    
    dfResList <- lapply(unique(df$year), function(i) {      
      yeardata <- subset(df, year == i)
      df <- runIncomeCalc(yeardata, i) 
      runResultsCalc(df, i)      
    })
    
    df1 <- do.call(rbind, dfIncList)
    df2 <- do.call(rbind, dfResList)
    
  • 1

    如果您功能化了步骤,则可以创建如下工作流程:

    calcFunc <- function(df) {
      ## Do something to the df, then return it
      df
    }
    
    processFunc <- function(fname) {
      ## Read in your table
      x <- read.table(fname)
    
      ## Do the calculation
      x <- calcFunc(x)
    
      ## Make a new file name (remember to change the file extension)
      new_fname <- sub("something", "else", fname)
    
      ## Write the .RData file
      save(x, file = new_fname)
    }
    
    ### Your workflow
    ## Generate a vector of files
    my_files <- list.files()
    
    ## Do the work
    res <- lapply(my_files, processFunc)
    

    或者,不要保存文件 . 省略 processFunc 中的 save 调用,并返回data.frame对象列表 . 然后使用 data.table::rbindlist(res)do.call(rbind, list) 创建一个大型data.frame对象 .

相关问题