【问题标题】:Trying to count the rows in a data.frame after removing NA's using na.omit()尝试在使用 na.omit() 删除 NA 后计算 data.frame 中的行数
【发布时间】:2016-01-31 02:47:37
【问题描述】:

我是编程新手,并尝试在删除 NA 值后计算文件中的行数。该函数应返回一个数据框,其中第一列是文件名,第二列是完整案例的数量。

这是我的代码:

complete <- function(directory, id = 1:332){
  setwd(directory)

  df <- data.frame()
  for (i in seq_along(id)){
    if (id[i] < 10){ 
    file_name <- paste("00",id[i],".csv", sep = "")
  }
    else if (id[i] >= 10 & id[i] < 100){
    file_name <- paste("0",id[i],".csv", sep = "")
  }
    else{
    file_name <- paste(id[i],".csv", sep = "")
  }
    file <- read.csv(as.character(file_name))
    newfile <- na.omit(file)
    #print(newfile)

    df <- data.frame(id = id, nobs = nrow(newfile))

  }

    print(df)

}

当我像这样传入一个 1:3 的向量时:complete("specdata", 1:3) 我得到以下输出:

id    nobs
1     243
2     243
3     243

其中 id 是列出的文件的文件数 1 到 332,nobs 等于完整案例的数量。

似乎它正在获取我的数据框中的最后一项并为每个 id 重复,我不知道如何解决它。作为初学者,我被这样的编程逻辑绊倒了。此外,我看到了一些其他解决这个问题的方法,但他们使用的是我不明白如何应用的 complete.cases。所以数据框中的每个 id 都应该有自己的完整案例计数(数据框中的 nobs 列)。

【问题讨论】:

  • 无法重现您的代码,因此任何人都很难理解问题所在。但是,我认为您应该将这一行 df &lt;- data.frame(id = id, nobs = nrow(newfile)) 替换为 df &lt;- data.frame(id = i, nobs = nrow(newfile))。一般建议:使用debug,这样您就可以逐步了解您的功能在做什么。
  • 另外,也许 complete.cases 在这里更有意义?不完全确定。
  • 问题不在nrow(newfile),而在id=id。查看之前的评论。
  • 嗨 Carlos,我将 id 更改为 i,很好。现在它返回正确数量的完整案例,但仅针对该特定 ID。如果我向它传递一个向量,我希望得到 ID 1、2 和 3 的一些完整案例,但它只给我最后一个 ID,即 3。

标签: r


【解决方案1】:

这是一个简短的版本供学习。请注意,我不必显式地paste 零,因为文件已经按顺序排列。单独尝试list.files(path="specdata", full.names=TRUE) 看看该函数的作用:

complete <- function(directory, id=1:332) {
  lst <- sapply(id, function(x) {
           df <- read.csv(list.files(path=directory, full.names=TRUE, pattern="csv")[x])
           sum(complete.cases(df))
  })
  data.frame(id,nobs=unlist(lst))
}

编辑

na.omitcomplete.cases 之间的区别是:

#Example
#Create data.frame with an NA value
df <- head(iris,3)
df[1,1] <- NA
df
#   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1           NA         3.5          1.4         0.2  setosa
# 2          4.9         3.0          1.4         0.2  setosa
# 3          4.7         3.2          1.3         0.2  setosa


#'na.omit' will return a data.frame with non-NA rows:
na.omit(df)
#   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 2          4.9         3.0          1.4         0.2  setosa
# 3          4.7         3.2          1.3         0.2  setosa

#'complete.cases' gives TRUEs and FALSEs for the rows with NAs
complete.cases(df)
#[1] FALSE  TRUE  TRUE

我使用“complete.cases”是因为我只想要非 NA 行的总数。我不需要 data.frame 本身,这是 'na.omit' 给出的。

我可以将 TRUE 和 FALSE 相加得到sum(complete.cases(df)) 的总数。该程序将知道将每个TRUE 转换为1 并将每个FALSE 转换为0

【讨论】:

  • 谢谢 Pierre,我们还没有了解 sapply 函数。这是我们下一课的内容。但我会研究你的代码。再次感谢。
  • 另外,使用 complete.cases 函数的人似乎比使用 na.omit 的人多。 complete.cases 更直观吗?
  • 这两个函数是相似的,因为它们都搜索具有至少一个 NA 值的行。我添加了一个示例来突出差异。
【解决方案2】:

您必须对代码进行一些更改... 首先,在循环之前的开头完全定义您的 data.frame。

df <- data.frame(id = id, nobs = NA)

其次,在您创建 newfile 后,将您的 df &lt;- data.frame... 指令替换为:

df[i,2] <- nrow(newfile)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-08
    • 2019-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-27
    相关资源
    最近更新 更多