使用R中的for循环记录分层数据

时间:2013-10-20 14:44:51

标签: r if-statement for-loop dataset

我有一个经常遇到的问题,我需要一种更有效的处理方式。我有一个凌乱的解决方案,发布在下面。

首先,我将生成一些与我的数据集类似的示例数据。

a <- c(1, 2, 2, 2, 3, 3)
b <- c("10/12", "10/12", "10/12", "10/13", "10/12", "10/12")
c <- c("c", "c", "pv", "c", "c", "c")
data <- matrix(NA, nrow = 6, ncol = 3)
data[,1] <- a
data[,2] <- b
data[,3] <- c

data

        [,1]    [,2]    [,3]
[1,]    1       10/12   c
[2,]    2       10/12   c
[3,]    2       10/12   pv
[4,]    2       10/13   c
[5,]    3       10/12   c
[6,]    3       10/12   c
# [,1] is a unique identifier, [,2] is a date, and [,3] is a type of occurrance

我需要做的是生成一个表,每天只为每个ID包含一个条目 列中显示该条目是仅对应'c','pv'仅对应'c&amp; pv',或'多个c'。 数据中无法使用多个pv

我这样做的方法是使用嵌套的for循环:

# I generate an object to post the data to
output.temp <- matrix(NA, nrow = 1, ncol = 4)

# Then I define the outer loop that subsets the data over each ID  
ids <- unique(data[,1])
n.ids <- length(ids)

for(i in 1:n.ids){
  temp.data <- subset(data, data[,1] == ids[i])

  dates <- unique(temp.data[,2])
  n.dates <- length(dates)  

# Then I define the inner loop that subsets the data for each ID over each date
  for(j in 1: n.dates){
    date.data <- subset(temp.data, temp.data[,2] == dates[j])

    # Then I apply the logic of what to write out
    if(nrow(date.data) == 1){
      if(date.data[,3] == 'c'){
      new.row <- cbind(date.data, "c only")
      output.temp <- rbind(output.temp, new.row)
      }
      if(date.data[,3] == 'pv'){
      new.row <- cbind(date.data, "pv only")
      output.temp <- rbind(output.temp, new.row)
      }
    }

    if(nrow(date.data) > 1){
      if('pv' %in% date.data[,3]){
      new.row <- cbind(matrix(date.data[1,], nrow = 1), c("c & pv"))
      output.temp <- rbind(output.temp, new.row)
    }
    else{
      new.row <- cbind(matrix(date.data[1,], nrow = 1), " multiple c only")
      output.temp <- rbind(output.temp, new.row)
    }
   }
  }
 }

# Finally, I drop the unnecessary row and column from the output object
output.final <- output.temp[-1,-3]

这很有效,但效率非常低。随着我的数据集变得越来越大(接近100万行), 它变得越来越成问题。

由于我是 R 的新手并且对编程经验不足,因此我们非常感谢您对替代策略的任何建议。

2 个答案:

答案 0 :(得分:1)

您应该能够使用下面的代码来获得所需输出的确切格式。

dataset <- data.table(dataset)
setnames(dataset, c('id','day','occurrence'))

dataset[,list(noofc = table(occurrence)['c'], noofpv = table(occurrence)['pv']), by = c('id','day')]

data.table是非常有效的数据框,也应该有助于解决数据大小问题

答案 1 :(得分:0)

我认为这个ddply()解决方案适合您:

library(plyr)
data <- data.frame(data)
names(data) <- c("id","date","type")
get.type <- function(x) ifelse("c" %in% x & "pv" %in% x, "c & pv",
                               ifelse(sum("c" == x) > 1,"multiple c",
                                      ifelse("c" %in% x,"c",
                                             ifelse("pv" %in% x,"pv","other"))))
ddply(data,.(id,date),summarize,type=get.type(type))

  id  date       type
1  1 10/12          c
2  2 10/12     c & pv
3  2 10/13          c
4  3 10/12 multiple c