2016-04-14 8 views
1

Es gibt viele Dateien in einem Verzeichnis, das Json formatierte Einträge in jeder Zeile hat. Die Größe der Dateien variiert von 5k bis 200MB. Ich habe diesen Code, um jede Datei zu gehen, analysiere die Daten, nach denen ich suche, und schließlich einen Datenrahmen. Dieses Skript braucht sehr viel Zeit, um fertig zu sein, es endet nie.ist es möglich, Datei lesen und analysieren in R

Gibt es eine Möglichkeit, es zu beschleunigen, damit ich die Dateien schneller lesen kann?

Code:

library(jsonlite) 
library(data.table) 

setwd("C:/Files/") 

#data <- lapply(readLines("test.txt"), fromJSON) 

df<-data.frame(Timestamp=factor(),Source=factor(),Host=factor(),Status=factor()) 
filenames <- list.files("Json_files", pattern="*.txt", full.names=TRUE) 

for(i in filenames){ 
    print(i) 
    data <- lapply(readLines(i), fromJSON) 
    myDf <- do.call("rbind", lapply(data, function(d) { 
    data.frame(TimeStamp = d$payloadData$timestamp, 
       Source = d$payloadData$source, 
       Host = d$payloadData$host, 
       Status = d$payloadData$status)})) 

    df<-rbind(df,myDf) 

}

Dies ist ein Beispieleintrag aber es gibt Tausende von Einträgen wie dies in der Datei:

{"senderDateTimeStamp":"2016/04/08 10:53:18","senderHost":null,"senderAppcode":"app","senderUsecase":"appinternalstats_prod","destinationTopic":"app_appinternalstats_realtimedata_topic","correlatedRecord":false,"needCorrelationCacheCleanup":false,"needCorrelation":false,"correlationAttributes":null,"correlationRecordCount":0,"correlateTimeWindowInMills":0,"lastCorrelationRecord":false,"realtimeESStorage":true,"receiverDateTimeStamp":1460127623591,"payloadData":{"timestamp":"2016-04-08T10:53:18.169","status":"get","source":"STREAM","fund":"JVV","client":"","region":"","evetid":"","osareqid":"","basis":"","pricingdate":"","content":"","msgname":"","recipient":"","objid":"","idlreqno":"","host":"WEB01","servermember":"test"},"payloadDataText":"","key":"app:appinternalstats_prod","destinationTopicName":"app_appinternalstats_realtimedata_topic","hdfsPath":"app/appinternalstats_prod","esindex":"app","estype":"appinternalstats_prod","useCase":"appinternalstats_prod","appCode":"app"} 

{"senderDateTimeStamp":"2016/04/08 10:54:18","senderHost":null,"senderAppcode":"app","senderUsecase":"appinternalstats_prod","destinationTopic":"app_appinternalstats_realtimedata_topic","correlatedRecord":false,"needCorrelationCacheCleanup":false,"needCorrelation":false,"correlationAttributes":null,"correlationRecordCount":0,"correlateTimeWindowInMills":0,"lastCorrelationRecord":false,"realtimeESStorage":true,"receiverDateTimeStamp":1460127623591,"payloadData":{"timestamp":"2016-04-08T10:53:18.169","status":"get","source":"STREAM","fund":"JVV","client":"","region":"","evetid":"","osareqid":"","basis":"","pricingdate":"","content":"","msgname":"","recipient":"","objid":"","idlreqno":"","host":"WEB02","servermember":""},"payloadDataText":"","key":"app:appinternalstats_prod","destinationTopicName":"app_appinternalstats_realtimedata_topic","hdfsPath":"app/appinternalstats_prod","esindex":"app","estype":"appinternalstats_prod","useCase":"appinternalstats_prod","appCode":"app"} 

{"senderDateTimeStamp":"2016/04/08 10:55:18","senderHost":null,"senderAppcode":"app","senderUsecase":"appinternalstats_prod","destinationTopic":"app_appinternalstats_realtimedata_topic","correlatedRecord":false,"needCorrelationCacheCleanup":false,"needCorrelation":false,"correlationAttributes":null,"correlationRecordCount":0,"correlateTimeWindowInMills":0,"lastCorrelationRecord":false,"realtimeESStorage":true,"receiverDateTimeStamp":1460127623591,"payloadData":{"timestamp":"2016-04-08T10:53:18.169","status":"get","source":"STREAM","fund":"JVV","client":"","region":"","evetid":"","osareqid":"","basis":"","pricingdate":"","content":"","msgname":"","recipient":"","objid":"","idlreqno":"","host":"WEB02","servermember":""},"payloadDataText":"","key":"app:appinternalstats_prod","destinationTopicName":"app_appinternalstats_realtimedata_topic","hdfsPath":"app/appinternalstats_prod","esindex":"app","estype":"appinternalstats_prod","useCase":"appinternalstats_prod","appCode":"app"} 
+0

@Tensibai, Ich habe einen Beispieleintrag, aber die Dateien können 10'von Tausenden solcher Einträge haben. – user1471980

+0

Sie können die Anzahl der Zeilen in den Dateien zählen, wodurch Sie eine gute Schätzung der Größe des endgültigen Datasets erhalten. R behandelt wachsende Objekte nicht sehr gut. Sie sollten versuchen, die 'rbind'-Aufrufe zu vermeiden. – niczky12

+1

@Tensibai, sorry, ich habe gerade 3 Einträge platziert. – user1471980

Antwort

3

Mit Ihrem Beispiel Daten in „c: /tmp.txt“:

> df <- jsonlite::fromJSON(paste0("[",paste0(readLines("c:/tmp.txt"),collapse=","),"]"))$payloadData[c("timestamp","source","host","status")] 
> df 
       timestamp source host status 
1 2016-04-08T10:53:18.169 STREAM WEB01 get 
2 2016-04-08T10:53:18.169 STREAM WEB02 get 
3 2016-04-08T10:53:18.169 STREAM WEB02 get 

so Ihren Code anzupassen eine Liste von Datenrahmen zu erhalten:

dflist <- lapply(filenames, function(i) { 
    jsonlite::fromJSON(
    paste0("[", 
      paste0(readLines(i),collapse=","), 
      "]") 
)$payloadData[c("timestamp","source","host","status")] 
}) 

die Idee ist, Ihre Linien zu verwandeln (von readLines) in einem großen json Array und dann den Datenrahmen erstellen, indem es als json Parsen . mit lapply auf Ihrer filenmaes Liste procide Sie mit einer Liste von Datenrahmen

Wie lmo bereits, zur Schau gestellt, wenn Sie wirklich nur einen Datenrahmen am Ende wollen Sie die data.table Pakete laden und rbindlist verwenden Sie dann auf dflist nur einen Datenrahmen zu erhalten.

Oder wenn Sie kurz im Speicher sind this thread kann Ihnen helfen.

+0

@Tendibai, Ihre Lösung arbeitet schneller. Wie konvertiere ich dflist in einen Datenrahmen? – user1471980

+1

@ user1471980 entweder 'largedf <- do.cal (" rbind ", dflist)' oder 'rbindlist'aus data.table Paket – Tensibai

+0

@Tenibai, ich weiß, dass Sie diese Frage beantwortet haben, aber was wäre, wenn es verschachtelte Objekte innerhalb des Payloaddata-Abschnitts gäbe dies: "" payloadData ": {" timestamp ":" 2016-04-07T00: 00: 00.093 "," beat ": {" name ":" server1 "," hostname ":" server1 "}," count ": "1", "Versender": "server1", "mem": {"gesamt": "18855256064", "frei": "7273639936", "actual_used": "3755769856", "used_p": "0.6242380717975277", " actual_free ":" 15099486208 "," used ":" 11581616128 "," actual_used_p ":" 0.2091895439262065 "}", wie würde ich die einzelnen verschachtelten Objekte wie Beat und Mem durchlaufen und den Hostnamen innerhalb von beat und actual_used mit mem abgreifen? – user1471980

1

Eine Geschwindigkeit bis Ihr for ersetzen Schleife mit lapply Dann fallen die endgültigen rbind. die Geschwindigkeit hier wäre, dass R nicht wiederholt eine immer größere Datei, df über Ihren "Haufen" von Dateien kopieren müsste. Das Ergebnis wäre in einer praktischen Liste gespeichert werden, die Sie entweder wie oder konvertieren zu einem data.frame in einem Rutsch verwenden:

# create processing function 
getData <- function(i) { 
    print(i) 
    data <- lapply(readLines(i), fromJSON) 
    myDf <- do.call("rbind", lapply(data, function(d) { 
    data.frame(TimeStamp = d$payloadData$timestamp, 
      Source = d$payloadData$source, 
      Host = d$payloadData$host, 
      Status = d$payloadData$status)})) 
} 

# lapply over files 
myDataList <- lapply(filenames, getData) 
Verwandte Themen