【问题标题】:R accessing data frames: What's going on here?R 访问数据框:这里发生了什么?
【发布时间】:2018-01-25 21:55:14
【问题描述】:

R 新手,所以可能是一个菜鸟问题。考虑以下代码,尤其是 for 循环:

library(lubridate)
#Read in all site files in the directory
sitefiles <- list.files(pattern = "\\.csv$")   #Get a list of all csv's in dir
sites <- list()                                #Create an empty list.
sites <- lapply(sitefiles, read.csv)          
names(sites) <- gsub("\\.csv$", "", sitefiles)  #Rename the list

for (site in names(sites)){
  site$time <-  dmy_hms(site$timestamp)
      #Error: $ operator is invalid for atomic vectors
}

好的,让我们试试这个:

for (site in sites){
  site$time <-  mdy_hms(site$timestamp)
}

它似乎对sites 列表中的数据框什么都不做。特别是命令 colnames(sites[[1]]) 在运行 for 循环之前和之后是相同的 - 没有添加任何列。

但是,发生了变化。 Rstudio 告诉我有一个新变量,一个名为site 的数据框,它确实添加了列时间。什么鬼???

这里发生了什么?如何成功执行此命令?

【问题讨论】:

  • site 还不是一个对象。此外,sites 是一个列表。因此,您必须 lapply 而不是循环。
  • 您希望在 for 循环中使用 sites[[site]]$time &lt;- dmy_hms(site$timestamp) 而不是 site$time &lt;- dmy_hms(site$timestamp)。查看this post 及其包含的链接以进行更长时间的讨论。帮助文件?"[" 也值得阅读 2 或 3 次。
  • 您必须提供str(sites) 的输出。如果您之前运行该行,names(sites) &lt;- gsub("\\.csv$", "", sitefiles) 您将获得一个命名列表。 for 循环遍历这些名称,sites[[site]] 将引用具有给定名称的列表元素。该行实际上应该是sites[[site]]$time &lt;- dmy_hms(sites[[site]]$timestamp)。我错过了对site$ 的第二次引用。也许您正试图在for 循环之外运行此行?如果您在全局环境中有一个名为 site 的对象,该对象是您在帖子中提到的列表,这将导致您看到的错误。
  • @Dirk,我添加了一个包含lapply 解决方案的答案。由于您的示例没有提供可重现的示例,您可以检查它是否有效。否则,我可以改进它。
  • @lok​​i 谢谢。它有效!

标签: r lubridate


【解决方案1】:

lapply 的解决方案如下所示:

sites <- lapply(sites, function(x) { 
  x$time <-  dmy_hms(x$timestamp)
  x
})

This summary 帮助您处理所有不同数据类型的子集。

这个案例的基本知识是:

  • sites 是一个包含多个 data.frames 的列表
  • lapply 获取所有这些 data.frames 并应用相同的功能
  • 然后返回这些修改后的 data.frames 的列表

小注:如果您以后依赖这些名称,您可能需要再次命名列表...

【讨论】:

    【解决方案2】:

    我找不到这方面的任何来源,但在本地对其进行测试,for 循环似乎正在为您正在迭代的列表中的项目创建本地副本。也许这就是推荐迭代 names 或者更确切地说是 apply 的原因。

    > a <- list(mtcars$cyl)
    > b <- list(mtcars$mpg)
    > x <- c(a, b)
    > tracemem(a)
    [1] "<0000000014731C68>"
    > tracemem(b)
    [1] "<00000000147711D8>"
    > for(myList in x) { print(tracemem(myList)) }
    [1] "<000000000C37E650>"
    [1] "<00000000096AED50>"
    

    site 变量保留是因为索引变量保留在周围环境中是标准行为。

    【讨论】:

    • 这实际上是有道理的。那么这样做的正确方法是什么?
    • 我认为lapply 将是最聪明的方式。除此之外,迭代names(sites) 并使用[[]] 运算符访问列表,正如上面@lmo 建议的那样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-04
    • 1970-01-01
    • 2013-11-03
    • 1970-01-01
    • 2020-03-12
    相关资源
    最近更新 更多