【问题标题】:Making multiple named data frames with loop使用循环制作多个命名数据帧
【发布时间】:2015-06-25 14:35:51
【问题描述】:

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

我正在尝试为我的更大问题的可重现问题创建一系列数据框。我想制作 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 等。

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

【问题讨论】:

  • 最好使用list,但是如果你需要4个不同的data.frame对象,list2env是一个选项。 list2env(setNames(datafrom, paste0('datafrom', years)), envir=.GlobalEnv)
  • 但说实话,你并不真正想要 4 个单独的 data.frame 变量。如果您将相关项目留在列表中,R 中的内容会更容易处理。
  • 这背后的原因是什么?
  • 第一次和最后一次 - 它允许您使用应用函数或循环轻松访问您的数据,这太棒了......

标签: r for-loop dataframe


【解决方案1】:

我将在这里演示一些(许多)技术,我将它们称为 (1) 蛮力、(2) 基于列表和 (3) 单个长格式 data.frame。

我将在示例中添加要应用于每个 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.frame,尽管许多经验丰富的 (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 %&gt;% filter(Year == 2010) %&gt;% myfunc()

(旁注:在尝试绘制聚合数据时,数据采用这种形式通常会更容易,尤其是在使用ggplot2-like 分层和美学时。)

反对“蛮力”的理由

在回答您的评论问题时,当使用相同的结构制作不同的变量时,很容易推断您将对它们中的每一个做同样的事情,依次或立即连续。在一般编程原则中,许多人试图概括他们所做的事情,以便如果可以完成一次,则可以在不(大量)调整代码的情况下完成任意次数。例如,比较上面两个示例中应用myfunc 的必要条件。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-16
    • 1970-01-01
    • 1970-01-01
    • 2023-02-16
    • 1970-01-01
    • 1970-01-01
    • 2021-11-25
    • 2019-10-13
    相关资源
    最近更新 更多