使用循环创建多个命名数据框

时间:2015-04-18 18:37:04

标签: r for-loop dataframe

在学习过程中。我没有问好我的第一个问题,所以我再次尝试并尽力让自己更清楚。

我试图为我的大问题创建一系列数据框,以便重现问题。我想制作4个数据框,每个数据框的年份命名不同。最后,我将合并这四个数据框来解释我遇到问题的地方。

这是最新的解决方案。这会运行,但会创建一个包含全局目录中没有任何帧的四个数据帧的列表。

 datafrom <- list()
 years <- c(2006,2008,2010,2012)

 for (i in 1:length(years)) {
  UniqueID <- 1:10 # <- Not all numeric - Kept as character vector
  Name <- LETTERS[seq( from = 1, to = 10 )]
  Entity_Type <- factor("This","That")
  Data1 <- rnorm(10)     
  Data2 <- rnorm(10) 
  Data3 <- rnorm(10) 
  Data4 <- rnorm(10) 
  Year <- years[i]
  datafrom[[i]] <- data.frame(UniqueID, Name, Entity_Type, Data1, Data2, Data3, Data4, Year)
 }

我想要4个独立的数据框,每个数据框都命名为datafrom2006,datafrom2008等等。

非常感谢您对我的学习的耐心。

1 个答案:

答案 0 :(得分:1)

我将在这里演示一些(很多)技术,我将它们称为(1)暴力,(2)基于列表的,以及(3)单个长格式数据。

我将在示例中添加要应用于每个data.frame的函数的使用。虽然做作,但它有助于说明问题:

## some constants used throughout
years <- c(2006, 2008, 2010, 2012)
n <- 10
myfunc <- function(x) {
    interestingPart <- x[ , grepl('^Data', colnames(x)) ]
    sapply(interestingPart, mean)
}

暴力

是的,你可以从一个循环中创建多个同名的和相同结构的data.frames,虽然它经常被许多有经验的( R ?)程序员所不满:

set.seed(42)
for (yr in years) {
    tmpdf <- data.frame(UniqueID=as.character(1:n),
                        Name=LETTERS[1:n],
                        Entity_Type=factor(c('this', 'that')),
                        Data1=rnorm(n),
                        Data2=rnorm(n),
                        Data3=rnorm(n),
                        Data4=rnorm(n),
                        Year=yr)
    assign(sprintf('datafrom%s', yr), tmpdf)
}
rm(yr, tmpdf)

ls()
## [1] "datafrom2006" "datafrom2008" "datafrom2010" "datafrom2012" "myfunc"      
## [6] "n"            "years"       

head(datafrom2006, n=2)
##   UniqueID Name Entity_Type      Data1      Data2      Data3      Data4 Year
## 1        1    A        this  1.3709584  1.3048697 -0.3066386  0.4554501 2006
## 2        2    B        that -0.5646982  2.2866454 -1.7813084  0.7048373 2006

为了查看每个data.frame的结果,通常会(尽管不总是)执行以下操作:

myfunc(datafrom2006)
##      Data1      Data2      Data3      Data4 
##  0.5472968 -0.1634567 -0.1780795 -0.3639041 
myfunc(datafrom2008)
##       Data1       Data2       Data3       Data4 
## -0.02021535  0.01839391  0.53907680 -0.21787537 
myfunc(datafrom2010)
##       Data1       Data2       Data3       Data4 
##  0.25110630 -0.08719458  0.22924781 -0.19857243 
myfunc(datafrom2012)
##      Data1      Data2      Data3      Data4 
## -0.7949660  0.2102418 -0.2022066 -0.2458678 

基于列表的

set.seed(42)
datafrom <- sapply(as.character(years), function(yr) {
                       data.frame(UniqueID=as.character(1:n),
                                  Name=LETTERS[1:n],
                                  Entity_Type=factor(c('this', 'that')),
                                  Data1=rnorm(n),
                                  Data2=rnorm(n),
                                  Data3=rnorm(n),
                                  Data4=rnorm(n),
                                  Year=yr)
                   }, simplify=FALSE)
str(datafrom)
## List of 4
##  $ 2006:'data.frame':    10 obs. of  8 variables:
##   ..$ UniqueID   : Factor w/ 10 levels "1","10","2","3",..: 1 3 4 5 6 7 8 9 10 2
##   ..$ Name       : Factor w/ 10 levels "A","B","C","D",..: 1 2 3 4 5 6 7 8 9 10
##   ..$ Entity_Type: Factor w/ 2 levels "that","this": 2 1 2 1 2 1 2 1 2 1
##   ..$ Data1      : num [1:10] 1.371 -0.565 0.363 0.633 0.404 ...
##   ..$ Data2      : num [1:10] 1.305 2.287 -1.389 -0.279 -0.133 ...
##   ..$ Data3      : num [1:10] -0.307 -1.781 -0.172 1.215 1.895 ...
##   ..$ Data4      : num [1:10] 0.455 0.705 1.035 -0.609 0.505 ...
##   ..$ Year       : Factor w/ 1 level "2006": 1 1 1 1 1 1 1 1 1 1
##  $ 2008:'data.frame':    10 obs. of  8 variables:
##   ..$ UniqueID   : Factor w/ 10 levels "1","10","2","3",..: 1 3 4 5 6 7 8 9 10 2
#### ...snip...

head(datafrom[[1]], n=2)
##   UniqueID Name Entity_Type      Data1      Data2      Data3      Data4 Year
## 1        1    A        this  1.3709584  1.3048697 -0.3066386  0.4554501 2006
## 2        2    B        that -0.5646982  2.2866454 -1.7813084  0.7048373 2006

head(datafrom[['2008']], n=2)
##   UniqueID Name Entity_Type      Data1       Data2      Data3       Data4 Year
## 1        1    A        this  0.2059986  0.32192527 -0.3672346 -1.04311894 2008
## 2        2    B        that -0.3610573 -0.78383894  0.1852306 -0.09018639 2008

然而,通过这个,你可以只用一个来测试你的功能:

myfunc(datafrom[[1]])
myfunc(datafrom[['2010']])

然后非常简单地运行所有这些函数:

lapply(datafrom, myfunc)
## $`2006`
##      Data1      Data2      Data3      Data4 
##  0.5472968 -0.1634567 -0.1780795 -0.3639041 
## $`2008`
##       Data1       Data2       Data3       Data4 
## -0.02021535  0.01839391  0.53907680 -0.21787537 
## $`2010`
##       Data1       Data2       Data3       Data4 
##  0.25110630 -0.08719458  0.22924781 -0.19857243 
## $`2012`
##      Data1      Data2      Data3      Data4 
## -0.7949660  0.2102418 -0.2022066 -0.2458678 

长格式数据

如果您将所有数据保存在同一个data.frame中,使用已定义的Year列,您仍然可以对其进行细分以探索各个年份:

longdf <- do.call('rbind.data.frame', datafrom)
rownames(longdf) <- NULL
longdf[c(1,11,21,31),]
##    UniqueID Name Entity_Type      Data1     Data2      Data3       Data4 Year
## 1         1    A        this  1.3709584 1.3048697 -0.3066386  0.45545012 2006
## 11        1    A        this  0.2059986 0.3219253 -0.3672346 -1.04311894 2008
## 21        1    A        this  1.5127070 1.3921164  1.2009654 -0.02509255 2010
## 31        1    A        this -1.4936251 0.5676206 -0.0861073 -0.04069848 2012

简单子集:

  • subset(longdf, Year == 2006),虽然子集有其他商品和其他商品。
  • by(longdf, longdf$Year, myfunc)
  • 如果使用library(dplyr),请尝试longdf %>% filter(Year == 2010) %>% myfunc()

(旁注:当试图绘制汇总数据时,当数据采用这种形式时,通常会更容易,尤其是在使用ggplot2时 - 例如分层和美观。)

反对&#34;蛮力&#34;

的理由

在回答你的评论问题时,在制作具有相同结构的不同变量时,很容易推断出你将依次或者连续地对每个变量做同样的事情。在一般编程原理中,许多人试图概括他们所做的事情,以便如果它可以做一次,它可以完成任意次数而无需(大量)调整代码。例如,比较上述两个示例中应用myfunc所需的内容。

此外,如果您以后想要汇总来自myfunc的电话的结果,那么在“蛮力”中会更加费力。示例(因为您必须捕获每个返回并手动组合),而其他两种技术可以使用更简单的汇总函数(例如,另一个lapply,或者ReduceFilter)。