在dplyr中使用count()时保留数据顺序

时间:2015-10-13 17:15:54

标签: r dplyr

我是一名Coursera学生学习R.我意识到这个特定的问题已经被SO所涵盖;但是,我没有看到有人尝试使用dplyr包来解决问题。

期望的输出:

> complete("specdata", 332:1)[1:2,]
     id nobs
313 332  301
312 331  353>

现在输出:

> complete("specdata", 332:1)[1:2,]
   ID nobs
1 332  301
2 331  353
> 

我的功能:

complete <- function(directory, id = 1:332) {
        airpolutionfiles <- list.files("assignment1data/specdata", full.names=TRUE)
        monitorsdata_all <- data.frame()
        for (i in 1:332) {
        monitorsdata_all <- rbind(monitorsdata_all, read.csv(airpolutionfiles[i]))
        }
        monitorsdata_all_subset <- subset(monitorsdata_all, complete.cases(monitorsdata_all) & ID %in% id)
        countbyid <- count(monitorsdata_all_subset, "ID")
        nobs <- rename(countbyid, c("freq"="nobs"))
        arrange(nobs, desc(ID))
}

我已经在SO上看到了许多试图改变多个数据文件绑定/循环方式的解决方案。虽然我已经意识到,按照我的功能所写的方式,这是次优的,我要求你提供的任何帮助都不会搞砸,因为我仍然试图抓住在基础知识上。

所以我的问题归结为......在使用以下方式进行子集化之后

monitorsdata_all_subset <- subset(monitorsdata_all, complete.cases(monitorsdata_all) & ID %in% id)

无论如何,按组计算观察数(在本例中为id)并保留ID列与行#的相对位置?

2 个答案:

答案 0 :(得分:3)

complete <- function(directory, id = 1:332) {
        airpolutionfiles <- list.files(directory, full.names=TRUE)
        nobs <- c()
        for (i in 1:length(id)) {
        monitorsdata_all <- read.csv(airpolutionfiles[id[i]])
        nobs[i] <- sum(complete.cases(monitorsdata_all))
        }
        data.frame(id, nobs)
}

在您的原始代码中,您会做出一些选择,这会减慢您的进度。您没有使用directory参数(我认为在编写示例时这是一个疏忽)。在将它们读入R之后,您还rbind了所有文件。我不会这样做。特别是阅读您不会使用的文件。

for ( i in 1:332) {

这很慢。即使这个人有id=1,你也会在每个文件中读到这个文件。为什么不直接读取用户选择的id文件。

接下来,我们计算完整的观察次数循环中而不是在循环之外。这样我们就有了一个循环来收集观察而不是数据帧。

sum(complete.cases(monitorsdata_all))

该命令将计算完整观察的数量。在创建nobs变量之后,很容易与用户选择的ID结合使用。

<强>奖金

您想了解如何按群组进行操作。我添加了四种方法来对R中的操作进行分组。甚至还有更多。

complete <- function(directory, id = 1:332) {
        airpolutionfiles <- list.files(directory, full.names=TRUE)
        monitorsdata_all <- data.frame()
        for (i in id) {
        monitorsdata_all <- rbind(monitorsdata_all, read.csv(airpolutionfiles[i]))
        }
        df <- subset(monitorsdata_all, complete.cases(monitorsdata_all))

        #one way to count number of ids
        nobs <- table(df$ID)

        #a different approach. I use "sulfate" but I could have used any column (they all have the same length)
        nobs <- tapply(df$sulfate, df$ID, length)

        #Two more ways with aggregate. I add [,2] after bc it is a data frame and I want the second column
        nobs <- aggregate(sulfate ~ ID, df, length)[,2]

        nobs <- aggregate(df$sulfate, list(df$ID), length)[,2]

        #then combine
        data.frame(id, nobs)
}

答案 1 :(得分:1)

不。 Imma首先更改你的代码,这样我就能弄清楚你在问什么

library(dplyr)

data = 
  "assignment1data/specdata" %>%
  list.files(full.names=TRUE) %>%
  { data_frame(file = .) } %>%
  mutate(order_in_folder = 1:n() ) %>%
  group_by(file, order_in_folder) %>%
  do( read.csv(file) )

frequency = 
  data %>%
  group_by(ID, order_in_folder) %>%
  summarize(nobs = n() ) %>%
  ungroup %>%
  arrange(order_in_folder)