CSV-Dateien aneinanderreihen

Wie rufe ich R-Funktionen auf, wie selektiere ich Daten, ich weiß nicht genau ....

Moderatoren: EDi, jogo

Antworten
schu

CSV-Dateien aneinanderreihen

Beitrag von schu »

Liebes R-Forum,

ich möchte in R gerne 394 .csv-Dateien miteinander verknüpfen und am Ende eine vollständige .csv-Datei erhalten.
Die Dateien sind in ihrer Struktur identisch. Sie bestehen jeweils aus 5 Spalten (Jahr, Nation, Insgesamt, Männlich, Weiblich). Da die ersten beiden Spalten (Jahr, Nation) für alle Dateien gleich sind, sollen sie nur einmal in der endgültigen Datei stehen. Die Werte für die drei weiteren Spalten, sollen von links nach rechts hintereinander geschrieben werden. Dabei wäre es wünschenswert, wenn die ersten 14 Zeilen und Zeile 17 der .csv-Dateien einfach missachtet werden, da diese Informationen nicht benötigt werden.

Meine bisherigen Recherchen und Versuche haben mich dahin gebracht, dass ich die Dateinamen zunächst alle in ein Objekt speicher und anschließend über den Befehl "rbind" aneinanderreihe. Leider werden die Dateien dabei alle untereinander geschrieben. Das sieht so aus:

Code: Alles auswählen

## Dateinamen in Objekt speichern
filenames <- list.files(path = "mergetest/", full.names = F)

## Read.csv für alle Dateien in filenames ausführen
test1 <- do.call("rbind", lapply(filenames, read.csv2, header = F))
Der "cbind" Befehl, welcher Objekte in Spalten nebeneinander schreibt gibt folgenden Fehler aus:

Code: Alles auswählen

Error in data.frame(..., check.names = FALSE) : 
  Argumente implizieren unterschiedliche Anzahl Zeilen: 1768, 3535
Die .csv-Dateien haben jedoch alle 3535 Zeilen. Das habe ich für meine 10 Testdokumente nachgesehen.

Ich danke vorab für jede Hilfe!

Viele Grüße
Sebastian
Benutzeravatar
EDi
Beiträge: 1599
Registriert: Sa Okt 08, 2016 3:39 pm

Re: CSV-Dateien aneinanderreihen

Beitrag von EDi »

Bitte ein reproduzierbares Beispiel posten (z.B. 2dateien).
Auch ist mir noch nicht klar wie die endgültige Tabelle aussehen soll.
Bitte immer ein reproduzierbares Minimalbeispiel angeben. Meinungen gehören mir und geben nicht die meines Brötchengebers wieder.

Dieser Beitrag ist lizensiert unter einer CC BY 4.0 Lizenz
Bild.
schu

Re: CSV-Dateien aneinanderreihen

Beitrag von schu »

Anbei die zwei Dateien und ein Screenshot, der zeigt, wie die finale .csv aussehen soll. Es wäre schön, ist aber nicht unbedingt nötig, dass in der finalen .csv-Datei die Leerzeilen nicht mehr vorhanden sind.

Ich hoffe es wird damit etwas klarer.

https://picload.org/view/droigorw/finalecsv.png.html


Viele Grüße
Sebastian
Dateianhänge
einw05978040.csv
(47.13 KiB) 55-mal heruntergeladen
einw05978036.csv
(55.89 KiB) 51-mal heruntergeladen
Benutzeravatar
EDi
Beiträge: 1599
Registriert: Sa Okt 08, 2016 3:39 pm

Re: CSV-Dateien aneinanderreihen

Beitrag von EDi »

Anbei die zwei Dateien und ein Screenshot, der zeigt, wie die finale .csv aussehen soll.
OK, bevor du dich an das bearbeiten mehrere Dateien zuwendest, solltest du zuerst mal schauen eine einzelne Datein in ein gescheites Format umzuormatieren. [Das format ist ziemlich schrottig...]

Was hast du denn da schon probiert?

?read.table. "skip" könnte schonmal nützlich sein...
Bitte immer ein reproduzierbares Minimalbeispiel angeben. Meinungen gehören mir und geben nicht die meines Brötchengebers wieder.

Dieser Beitrag ist lizensiert unter einer CC BY 4.0 Lizenz
Bild.
schu

Re: CSV-Dateien aneinanderreihen

Beitrag von schu »

[Das format ist ziemlich schrottig...]
Wie meinst Du das? Findest Du das Ausgangsformat schrottig, oder wie ich es mir am Ende vorstelle?

Ich habe eine der Dateien jetzt wie folgt umformatiert und das kommt meiner Wunschvorstellung schon sehr nahe:

Code: Alles auswählen

table1 <- read.csv(file = "mergetest/einw05974044.csv", 
                   header = T,
                   sep = ";",                    
                   skip = 8,
                   nrows = 1751,
                   blank.lines.skip = T,
                   na.strings = c("-", "."),
                   col.names = c("Jahr", "Region", "insgesamt", "männlich", "weiblich"))
Was fehlt ist, dass die Nummer aus dem Dateinamen (hier: 05974044) in den drei Spalten "insgesamt", "männlich" und "weiblich" an den Anfang geschrieben wird, so dass die Spalten am Ende "05974044insgesamt", usw. heißen. Ist es anschließend möglich das ganze als Funktion zu definieren und über alle Dateien im Objekt filenames (s. erster Post) laufen zu lassen? Oder denke ich da gerade falsch?
Benutzeravatar
EDi
Beiträge: 1599
Registriert: Sa Okt 08, 2016 3:39 pm

Re: CSV-Dateien aneinanderreihen

Beitrag von EDi »

Wie meinst Du das? Findest Du das Ausgangsformat schrottig, oder wie ich es mir am Ende vorstelle?
Eingangsformat... Hat mehrere Probleme...
Hier eine Möglichkeit beide Dateien einzulesen (mit einpaar extra Schritten die nicht zwingend notwenig sind...):

Code: Alles auswählen

files <- list.files('Downloads/', pattern = 'einw.*\\.csv', full.names = TRUE)

# apply / develop data cleaning pipeline for one file -----------------------
tab <- read.table(file = files[1], 
                   header = FALSE,
                   sep = ";", 
                   as.is = TRUE,
                   na.strings = c("-", ".", ""),
                   fill = TRUE,
                   blank.lines.skip = FALSE)
# remove header rows
tab <- tab[-c(1:which(tab$V3 == "Personen")), ]
# remove tail rows
tab <- tab[-c(min(which(tab$V1 == "_____"), nrow(tab))), ]
# set colnames
colnames(tab) <- c("Jahr", "Region", "insgesamt", "männlich", "weiblich")
# remove empty rows
tab <- tab[!is.na(tab$insgesamt), ]
# fill NAs with zero
tab$männlich[is.na(tab$männlich)] <- 0
tab$weiblich[is.na(tab$weiblich)] <- 0

# make numeric
tab$männlich <- as.numeric(tab$männlich)
tab$weiblich <- as.numeric(tab$weiblich)
tab$insgesamt <- as.numeric(tab$insgesamt)
# check if all are equal
all(tab$männlich + tab$weiblich  == tab$insgesamt)
#  remove redundant information
tab$insgesamt <- NULL

# bring to long format
library(tidyr)
tab <- gather(tab, 'geschlecht', 'anzahl', -Jahr, - Region)
head(tab)



# Warp into function and apply to all files -------------------------------

clean_file <- function(file) {
  tab <- read.table(file = file, 
                    header = FALSE,
                    sep = ";", 
                    as.is = TRUE,
                    na.strings = c("-", ".", ""),
                    fill = TRUE,
                    blank.lines.skip = FALSE)
  # remove header rows
  tab <- tab[-c(1:which(tab$V3 == "Personen")), ]
  # remove tail rows
  tab <- tab[-c(min(which(tab$V1 == "_____"), nrow(tab))), ]
  # set colnames
  colnames(tab) <- c("Jahr", "Region", "insgesamt", "männlich", "weiblich")
  # remove empty rows
  tab <- tab[!is.na(tab$insgesamt), ]
  # fill NAs with zero
  tab$männlich[is.na(tab$männlich)] <- 0
  tab$weiblich[is.na(tab$weiblich)] <- 0
  
  # make numeric
  tab$männlich <- as.numeric(tab$männlich)
  tab$weiblich <- as.numeric(tab$weiblich)
  tab$insgesamt <- as.numeric(tab$insgesamt)
  
  # check if all are equal
  if(!all(tab$männlich + tab$weiblich  == tab$insgesamt)) {
    warning('File ', file, 'has non-consistent data!')
  }
  #  remove redundant information
  tab$insgesamt <- NULL
  
  # bring to long format
  tab <- gather(tab, 'geschlecht', 'anzahl', -Jahr, - Region)
  # set filename in column 
  tab$source <- file
  return(tab)
}
# check function
clean_file(files[2])
# apply function to each file and store in list
cleaned_files <- lapply(files, clean_file)

# combine all tables into one
do.call(rbind, cleaned_files)
Bitte immer ein reproduzierbares Minimalbeispiel angeben. Meinungen gehören mir und geben nicht die meines Brötchengebers wieder.

Dieser Beitrag ist lizensiert unter einer CC BY 4.0 Lizenz
Bild.
schu

Re: CSV-Dateien aneinanderreihen

Beitrag von schu »

Vielen Dank für deinen Lösungsansatz EDi :!: . Es löst mein Problem, auch wenn ich es mir etwas anders vorgestellt habe und einigen der Befehle nicht ganz folgen kann.
Benutzeravatar
EDi
Beiträge: 1599
Registriert: Sa Okt 08, 2016 3:39 pm

Re: CSV-Dateien aneinanderreihen

Beitrag von EDi »

schu hat geschrieben: Mo Nov 20, 2017 12:14 pm Vielen Dank für deinen Lösungsansatz EDi :!: . Es löst mein Problem, auch wenn ich es mir etwas anders vorgestellt habe und einigen der Befehle nicht ganz folgen kann.
Na dann, Zeile für Zeile durchgehen, schauen was passiert und eventuell modifizieren.
Bitte immer ein reproduzierbares Minimalbeispiel angeben. Meinungen gehören mir und geben nicht die meines Brötchengebers wieder.

Dieser Beitrag ist lizensiert unter einer CC BY 4.0 Lizenz
Bild.
Antworten