2016-02-28 129 views
0

我在一個目錄中有超過300個csv文件。 將CSV文件具有以下結構在循環中填充數據幀

id    Date  Nitrate  Sulfate 
id of csv file Some date Some Value Some Value 
id of csv file Some date Some Value Some Value 
id of csv file Some date Some Value Some Value 

我希望計算在該文件中不包括NA每個csv文件的行數並將其存儲在數據幀,其具有兩列:(1)ID &(2) NOBS。

這裏是我的代碼:

complete <-function(directory,id){ 
    filenames <-sprintf("%03d.csv", id) 
    filenames <-paste(directory,filenames,sep = '/') 
    dataframe <-data.frame(id=numeric(0),nobs=numeric(0)) 
    for(i in filenames){ 
    data <- read.csv(i) 
    dataframe[i,dataframe$id]<-data[data$id] 
    dataframe[i,dataframe$nobs]<-nrow(data[!is.na(data$sulfate & data$nitrate),]) 
    } 

    dataframe 

} 

的問題,當我嘗試填充在循環中出現數據幀,好像它不填充數據幀,返回NULL我。我知道我在做一些愚蠢的事情。

+0

你檢查這個職位? http://stackoverflow.com/questions/14358629/counting-the-number-of-rows-of-a-series-of-csv-files – 2016-02-28 10:01:53

回答

2

的問題是在這兩條線:

dataframe[i,dataframe$id]<-data[data$id] 
dataframe[i,dataframe$nobs]<-nrow(data[!is.na(data$sulfate & data$nitrate),]) 

如果你想擴展數據幀,請使用rbind功能。但請注意,這不是有效的方式,因爲它分配新的內存並複製所有數據並添加一個新行。的有效途徑是分配數據框足夠大在這一行:

dataframe <-data.frame(id=numeric(0),nobs=numeric(0)) 

相反的0,行的預期數量的使用數量。

所以,最簡單的方法就是

dataframe <- rbind(dataframe, data.frame(id=data$id[1], nobs=nrow(data[!is.na(data$sulfate) & !is.na(data$nitrate),])) 

更有效的方法是類似的東西:

dataframe <-data.frame(id=numeric(numberOfRows),nobs=numeric(numberOfRows)) 

之後,在循環:

dataframe[i,]$id<-data$id[1] 
dataframe[i,]$nobs<-nrow(data[!is.na(data$sulfate) & !is.na(data$nitrate),]) 

更新:我將用於填充數據幀的值更改爲data$id[1]nrow(data[!is.na(data$sulfate) & !is.na(data$nitrate),])

+0

@bartoszukum我試過你的方法,但它以這個錯誤結束。錯誤在'$ < - 。data.frame'('* tmp *',「id」,value = list()): 替換有1461行,數據有1 –

+0

@Farrukh Ahmed對不起,我認爲您使用的值填充數據幀是有效的。請考慮它。我假設數據$ id在每個位置都有相同的值,所以我首先使用。要使用is.na,必須分別檢查每列,並在此之後進行邏輯「和」。 – bartoszukm

+0

非常感謝@bartoszukum。它的工作原理是 。 –

3

我通常更喜歡將行添加到預先分配的列表中,然後將它們綁定在一起。這裏有一個工作示例:

##### fake read.csv function returning random data.frame 
# (just to reproduce your case, remove this from your code...) 
read.csv <- function(fileName){ 
    stupidHash <- sum(as.integer(charToRaw(fileName))) 
    if(stupidHash %% 2 == 0){ 
    return(data.frame(id=stupidHash,date='2016-02-28', 
         nitrate=c(NA,2,3,NA,5),sulfate=c(10,20,NA,NA,40))) 
    }else{ 
    return(data.frame(id=stupidHash,date='2016-02-28', 
         nitrate=c(4,2,3,NA,5,9),sulfate=c(10,20,NA,NA,40,50))) 
    } 
} 
##### 

complete <-function(directory,id){ 
    filenames <-sprintf("%03d.csv", id) 
    filenames <-paste(directory,filenames,sep = '/') 
    # here we pre-allocate a list of lenght=length(filenames) 
    # where we will put the rows of our future data.frame 
    rowsList <- vector(mode='list',length=length(filenames)) 
    for(i in 1:length(filenames)){ 
    filename <- filenames[i] 
    data <- read.csv(filename) 
    rowsList[[i]] <- data.frame(id=data$id[1], 
           nobs=sum(!is.na(data$sulfate) & !is.na(data$nitrate))) 
    } 
    # here we bind all the previously created rows together into one data.frame 
    DF <- do.call(rbind.data.frame, rowsList) 
    return(DF) 
} 

用例:

res <- complete(directory='dir',id=1:3) 

> res 
    id nobs 
1 889 4 
2 890 2 
3 891 4