2017-07-19 2 views
0

Ich bin ziemlich neu bei R und ein bisschen fest auf, was ich fühle, ist wahrscheinlich eine häufige Operation zu tun. Ich habe eine Reihe von Dateien (57 mit ~ 1,5 Milliarden Zeilen kumulativ um 6 Spalten), auf denen ich grundlegende Funktionen ausführen muss. Ich bin in der Lage, diese Dateien zu lesen und die Berechnungen durchzuführen, ich brauche kein Problem, aber ich stolpere in der endgültigen Ausgabe. Ich stelle mir vor, dass die Funktion jeweils an einer Datei arbeitet, die bearbeitete Datei ausgibt und auf die nächste übergeht.Verwenden von Lapply, um eine Funktion über eingelesene Liste von Dateien anzuwenden und die Ausgabe als neue Liste von Dateien zu speichern

Nach den Berechnungen möchte ich 57 neue TXT-Dateien ausgeben, die nach der Datei benannt sind, aus der die Eingabedaten stammen. Bis jetzt bin ich in der Lage, die Berechnungen auf kleineren Testdatensätzen durchzuführen und 1 angehängte .txt Datei auszuspucken, aber das ist nicht, was ich als eine Endausgabe will.

#list filenames 
files <- list.files(path=, pattern="*.txt", full.names=TRUE, recursive=FALSE) 

#begin looping process 
loop_output = lapply(files, 
function(x) { 

#Load 'x' file in 
DF<- read.table(x, header = FALSE, sep= "\t") 

#Call calculated height average a name 
R_ref= 1647.038203 

#Add column names to .las data 
colnames(DF) <- c("X","Y","Z","I","A","FC") 

#Calculate return 
DF$R_calc <- (R_ref - DF$Z)/cos(DF$A*pi/180) 

#Calculate intensity 
DF$Ir_calc <- DF$I * (DF$R_calc^2/R_ref^2) 

#Output new .txt with calcuated columns 
write.table(DF, file=, row.names = FALSE, col.names = FALSE, append = TRUE,fileEncoding = "UTF-8") 

}) 

Meine neuesten Code Bemühungen haben zu Chaos schon mit dem intial lapply/sapply Funktion als so:

#begin looping process 
loop_output = sapply(names(files), 
function(x) { 

Neben der Ausgangsleitung:

#Output new .csv with calcuated columns 
write.table(DF, file=paste0(names(DF), "txt", sep="."), 
row.names = FALSE, col.names = FALSE, append = TRUE,fileEncoding = "UTF-8") 

Von dem, was ich habe die Dateibenennungsfunktion während der write.table-Ausgabe gelesen, könnte einer der Schlüssel sein, die ich noch nicht vollständig mit dem Rest des Skripts ausgerichtet habe. Ich habe eine Menge anderer Fragen worden sehen, die ich anwendbar fühlte waren:

Using lapply to apply a function over list of data frames and saving output to files with different names

Write list of data.frames to separate CSV files with lapply

bis kein Glück. Ich schätze jede Einsichten oder Pfade in die richtige Richtung bei der Eingabe von x Anzahl von Dateien, führe die gleiche Funktion bei jedem aus und gebe dann die gleiche x Anzahl von Dateien aus. Vielen Dank.

+0

'map()' aus dem 'purrr' Paket funktioniert gut dafür.Sie können einen Ordner mit Dateien einlesen, sie getrennt halten und die gleichen Operationen für jeden durchführen. Ich würde eine Funktion definieren, um die erforderlichen Operationen auszuführen und dann einzulesen, umzuwandeln und dann mit 'map()' – Mako212

+0

zu schreiben. Das Problem an Ihrem 'lapply' Code ist also nur die angehängte Textdatei? – Parfait

+0

@Parfait Nein, es kommt zu einer ähnlichen Schlussfolgerung, wie ich es möchte: dh es berechnet, was ich berechnen muss und liefert eine korrekte Ausgabe. Ich möchte jedoch 57 einzelne neue Dateien anstelle der 1 angehängten Datei für die Verwaltung der Datengröße und für das, was ich mit den Dateien machen möchte, im nächsten Schritt meines Arbeitsprozesses ausgeben. –

Antwort

1

Der Grund für die Ausgabe auf die gleiche Datei gerichtet ist, ist wahrscheinlich, dass file = paste0(names(DF), "txt", sep=".") den gleichen Wert für jede Iteration zurückgibt. Das heißt, DF muss in jeder Iteration die gleichen Spaltennamen haben, daher wird names(DF) gleich sein und paste0(names(DF), "txt", sep=".") wird gleich sein. Zusammen mit der Option append = TRUE ist das Ergebnis, dass alle Ausgaben in dieselbe Datei geschrieben werden.

In der anonymen Funktion ist x der Name der Eingabedatei. Anstatt names(DF) als Basis für den Namen der Ausgabedatei zu verwenden, könnten Sie eine Umwandlung dieser Zeichenkette vornehmen.

Beispiel.

x <- "/foo/raw_data.csv" 

Innerhalb der Funktion Da Sie so etwas wie dieses

infile <- x 
outfile <- file.path(dirname(infile), gsub('raw', 'clean', basename(infile))) 

outfile 
[1] "/foo/clean_data.csv" 

dann den neuen Namen verwenden für die Ausgabe, mit append = FALSE tun könnte (es sei denn, Sie es brauchen um wahr zu sein)

write.table(DF, file = outfile, row.names = FALSE, col.names = FALSE, append = FALSE, fileEncoding = "UTF-8") 
+0

danke für deine Anregungen und Vorschläge. Dies erwies sich als der Trick! Innerhalb der Funktion setze ich 'inFile' als erste Zeile und dann 'outFile' direkt vor meiner Ausgabezeile, wie Sie es geschrieben haben (mit append = FALSE in der write.table-Zeile). Mit sapply in der Funktionszeile funktionierte mein Code nicht, mit platter in der Funktionszeile. Nochmals vielen Dank. –

+0

Ich bin froh, Ihnen zu helfen, und wenn das Problem gelöst ist, akzeptieren Sie bitte die Antwort, um es anderen mitzuteilen. (ref: https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) – Damian

+0

Ich mag die gsub ('roh', 'sauber' ... Funktion auch. Hilft mit ein Überschreibungsproblem, das ich verhindern wollte, ich akzeptiere deine Antwort –

0

Code verwenden, ist dies die allgemeine Idee:

require(purrr) 

#list filenames 
files <- list.files(path=, pattern="*.txt", full.names=TRUE, recursive=FALSE) 


#Call calculated height average a name 
R_ref= 1647.038203 

dfTransform <- function(file){ 
    colnames(file) <- c("X","Y","Z","I","A","FC") 

    #Calculate return 
    file$R_calc <- (R_ref - file$Z)/cos(file$A*pi/180) 

    #Calculate intensity 
    file$Ir_calc <- file$I * (file$R_calc^2/R_ref^2) 
    return(file) 
} 

output <- files %>% map(read.table,header = FALSE, sep= "\t") %>% 
    map(dfTransform) %>% 
    map(write.table, file=paste0(names(DF), "txt", sep="."), 
    row.names = FALSE, col.names = FALSE, append = TRUE,fileEncoding = "UTF-8") 
+0

vielen Dank für Ihre Antwort und die Einführung in das" Purrr "-Paket. Ich habe Ihre exemplarische Vorgehensweise ausprobiert und beim Schritt map (dfTransform) einen Fehler festgestellt. Fehler in Namen (x) <- Wert: 'Namen' Attribut [6] muss die gleiche Länge wie der Vektor sein [1] –

+0

@forest_codes überprüfen Sie, dass a) alle Ihre Dateien die gleiche Anzahl von Spalten haben, b) dass Sie Geben Sie einen Namen für jede Spalte im Namensvektor 'Spaltennamen (Datei) <- c (" X "," Y "," Z "," I "," A "," FC ")' (Sie müssen angeben ein Wert für jede Spalte). Wenn das immer noch nicht funktioniert, versuchen Sie stattdessen 'col.names' als Argument in' read.table' zu ​​übergeben. – Mako212

+0

Fortsetzung Das hat mich ein wenig perplex, die Daten sind im .txt Format und "\ t" getrennt und dieser Punkt sollte in 6 Spalten aufgeteilt werden. Ich glaube nicht, dass es etwas mit Ihrem Code zu tun hat, aber ich sehe auch nicht schnell den Fehler in meinen Daten (Ich habe 2, 5 Zeilen Dateien für mein kleines Testset) –

Verwandte Themen