Warum als factor eingelesen?

Wie erweitere ich R um eigene Funktionen oder Pakete? Welches Paket ist passend für meine Fragestellung?

Moderatoren: EDi, jogo

Antworten
bigben
Beiträge: 2771
Registriert: Mi Okt 12, 2016 9:09 am

Warum als factor eingelesen?

Beitrag von bigben »

Hallo!

Vielleicht kennt Ihr mein Problem von gestern abend: Ich lese ein csv in R ein und eine Spalte, die ganz klar numeric sein müsste wird als factor eingelesen. Sowas haben wir im Forum ja immer mal wieder und deshalb ist sofort klar, dass irgendwo in dieser Spalte möglicherweise ein einziger Eintrag ist, der nicht als Zahl gelesen wird. Ich habe also gemacht, was ich im Forum auch machen würde: names(spalte) aufgerufen und mit meinen Augen gesucht, welches nicht passt. Dummerweise war es visuell nicht so leicht zu erkennen und was hätte ich gemacht, wenn es nicht 208 sondern zwanzigtausend Zeilen gewesen wären?

Da wurde mir klar, es müsste eine function spot.factor.issue() geben. Diese Funktion ruft man mit einem Factor-Vector als Argument auf und sie weist einen auf die Elemente des Vektors hin, die einer Konversion in Zahlen entgegen stehen. Eine naive Implementation könnte vielleicht so aussehen:

Code: Alles auswählen

spot.factor.issue <- function(column)
  which(is.na(as.numeric(as.character(column))))
Angewendet in einem reproduzierbaren Beispiel so:

Code: Alles auswählen

expl.1 <- factor(c("-6.32", "-5.66", "-5.64","-5.58", "-4.7", "-4.69", 
                 "-3.75", "-2.92", "-2.89", "-2.56", "-2.51", "-1.75",
                 "-1.1", "-0.37", "0.05", "0.6", "0,67", "1.64", "1.89",
                 "2.36", "2.6", "3", "3.37", "4.17", "4.81", "O.93"))
              
spot.factor.issue(expl.1)
Die naive Implementierung hätte gestern Abend für mich schon funktioniert, scheitert aber, wenn der Datensatz NAs enthält.

Code: Alles auswählen

expl.2 <- read.table(text = "1.5 1.6 1.7 1,8
                     NA NA 1.7 1.8
                     NA NA 1.7 NA")
spot.factor.issue(expl.2[[4]])
Und als Deutscher hätte ich gerne auch eine Version, bei der man das Komma als Dezimaltrenner verwenden kann. Bestimmt fallen Euch noch weitere wünschenswerte Eigenschaften einer solchen Funktion ein.

In meiner Vision würden wir gemeinsam eine möglichst fähige Funktion erstellen und Student würde sie irgendwo auf dem Server hinterlegen, sodass man bei der nächsten Anfrage "Warum erkennt R meine Zahlen nicht?" einfach schreiben könnte:
Lass mal folgendes Laufen und poste das Ergebnis:

Code: Alles auswählen

source("http://forum.r-statistik.de/faktorproblem.R")
spot.factor.issue(spaltenname)
Na gut, wenn man das mit dem source nicht gut findet, könnte man ja einen FAQ-Post erstellen.

Bin ich der einzige, der das gut fände? Oder gib es das schon und ich versuche, das Rad neu zu erfinden?

Viele Grüße,
Bernhard
---
Programmiere stets so, dass die Maxime Deines Programmierstils Grundlage allgemeiner Gesetzgebung sein könnte
Benutzeravatar
EDi
Beiträge: 1599
Registriert: Sa Okt 08, 2016 3:39 pm

Re: Warum als factor eingelesen?

Beitrag von EDi »

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.
jogo
Beiträge: 2085
Registriert: Fr Okt 07, 2016 8:25 am

Re: Warum als factor eingelesen?

Beitrag von jogo »

Hallo Bernhard,

die gesuchte Function heißt as.numeric() und sie meldet sich mit den NA's.
Ansonsten heißt es im Zweifelsfall: stringsAsFactors=FALSE

Gruß, Jörg
bigben
Beiträge: 2771
Registriert: Mi Okt 12, 2016 9:09 am

Re: Warum als factor eingelesen?

Beitrag von bigben »

jogo hat geschrieben: Do Mär 07, 2019 5:55 pmdie gesuchte Function heißt as.numeric() und sie meldet sich mit den NA's.
Ich weiß. Die habe ich die ja oben verwendet. Hilft halt nur mäßig, wenn auch reguläre NAs in den Daten vorkommen, wie in meinem Beispiel 2. Die beiden Antworten in EDis Link addressieren das auf zwei verschiedene Weisen. Die zweite, auf stackoverflow weniger geschätzte Antwort verwendet grepl. Das kann man auch auf ein Komma als Dezimaltrenner erweitern.

Danke für den Link! Habe auch die Funktion suppressWarnings neu gelernt.

Schönen Abend noch,
Bernhard
---
Programmiere stets so, dass die Maxime Deines Programmierstils Grundlage allgemeiner Gesetzgebung sein könnte
jogo
Beiträge: 2085
Registriert: Fr Okt 07, 2016 8:25 am

Re: Warum als factor eingelesen?

Beitrag von jogo »

Hallo Bernhard,

bei schwierigen Datenkonversionen lautet meine oberste Devise: Nie die Originaldaten überschreiben!
Deshalb würde ich wie folgt vorgehen:
1. Einlesen mit stringsAsFactors=FALSE
2. neue Spalte mit as.numeric() erzeugen
3. select(..., is.na(neueSpalte) & (!is.na(alteSpalte))
Danach müssen die Zeichenersetzungsfunktionen ran.

Gruß, Jörg
p.s.:
"alteSpalte" war nicht despektierlich gemeint.
Antworten