具有for循环的子集DF通过函数运行每个子集

时间:2019-05-07 16:51:45

标签: r for-loop

我有一个10年站点上5年的植物种群数据集,站点内共有37个样带。以下是带有一些数据的GoogleDoc链接: https://docs.google.com/spreadsheets/d/1VT-dDrTwG8wHBNx7eW4BtXH5wqesnIDwKTdK61xsD0U/edit?usp=sharing

我总共有101种独特的组合。

我需要对每个唯一的数据集进行子集化,以便可以通过一些代码来运行每个数据。这段代码将为我提供一列输出,我需要将其添加回原始数据帧,以便可以在整个数据集上运行LM。我曾希望编写一个for循环,在其中可以对每个唯一组合进行子集处理,在每个组合上运行代码,然后将每个模型的输出附加回原始数据集。我编写子集循环的尝试都未能产生简单的输出。

我创建了一个“ SiteTY”列,其中包含唯一的“站点”,“横断面”和“年份”组合。因此,“ PWR 832015”是PWR Transect 83 Year 2015站点。我尝试使用它来循环并填充一个空矩阵,以作为概念证明。

transect=unique(dat$SiteTY)
ntrans=length(transect)
tmpout=matrix(NA, nrow=ntrans, ncol=2)

for (i in 1:ntrans) {
   df=subset(dat, SiteTY==i)
   tmpout[i,]=(unique(df$SiteTY))
}

当我这样做时,我注意到df没有观察到。如果我将“ i”替换为已知值(例如PWR 832015)并分别运行for循环的每一行,则它将正确填充。如果我将is.factor()用于i或PWR 832015,则两者均返回FALSE。 此特定代码也给我错误:

  

[,-*tmp*,,i,value = mean(df $ Year))中的错误:下标超出范围

我只能假设发生这种情况是因为数据帧为空。 我已经读了足够多的SO帖子,知道for循环是棘手的,但是我尝试的迭代次数超过了我记得在过去3年内使这项工作无效的尝试。

任何有关循环或在获得我需要的输出时避免循环的方法的提示。

2 个答案:

答案 0 :(得分:1)

根据您的需要,我需要对每组唯一的数据进行子集处理,运行一个函数,获取输出并计算一个新值,并考虑两条路线:

  1. 如果函数需要并返回单个数字列,请使用ave
  2. 如果函数需要一个数据帧并返回任何内容,请使用by

ave

返回一个分组的行内聚合列,该列对组中的每个成员都有重复的值。下面,with用作上下文管理器,以避免重复的dat$引用。

# BY SITE GROUPING
dat$New_Column <- with(dat, ave(Numeric_Column, Site, FUN=myfunction))

# BY SITE AND TRANSECT GROUPINGS
dat$New_Column <- with(dat, ave(Numeric_Column, Site, Transect, FUN=myfunction))

# BY SITE AND TRANSECT AND YEAR GROUPINGS
dat$New_Column <- with(dat, ave(Numeric_Column, Site, Transect, Year, FUN=myfunction))

by

为每个可能的分组返回对象的命名列表或函数返回的任何内容。对于多个分组,使用tryCatch的原因是 myfunction 可能返回错误的所有可能组合中的数据框项目可能为空。

# BY SITE GROUPING
obj_list <- by(dat, dat$Site, function(sub) {    
        myfunction(sub)  # RUN ANY OPERATION ON sub DATA FRAME
})

# BY SITE AND TRANSECT GROUPINGS
obj_list <- by(dat, dat[c("Site", "Transect")], function(sub) {    
        tryCatch(myfunction(sub),
                 error = function(e) NULL)
})

# BY SITE AND TRANSECT AND YEAR GROUPINGS
obj_list <- by(dat, dat[c("Site", "Transect", "Year")], function(sub) {    
        tryCatch(myfunction(sub),
                 error = function(e) NULL)
})

# FILTERS OUT ALL NULLs (I.E., NO LENGTH)
obj_list <- Filter(length, obj_list)

# BUILDS SINGLE OUTPUT IF MATRIX OR DATA FRAME
final_obj <- do.call(rbind, obj_list)

答案 1 :(得分:0)

这是使用library(dplyr) # Group by species (site, transect, etc) and summarise species_summary <- iris %>% group_by(Species) %>% summarise(mean.Sepal.Length = mean(Sepal.Length), mean.Sepal.Width = mean(Sepal.Width)) # A data.frame with one row per species, one column per statistic species_summary # Join the summary stats back onto the original data iris_plus <- iris %>% left_join(species_summary, by = "Species") head(iris_plus) 库的另一种方法,其中我为每个组创建一个汇总统计信息的data.frame,然后将其重新加入:

mxgraph