Wie konvertiere ich eine Datenrahmenspalte in einen numerischen Typ?


Antworten:


267

Da (noch) niemand ein Häkchen bekommen hat, gehe ich davon aus, dass Sie ein praktisches Problem haben, hauptsächlich, weil Sie nicht angegeben haben, in welchen Vektortyp Sie konvertieren möchten numeric. Ich schlage vor, dass Sie die transformFunktion anwenden , um Ihre Aufgabe abzuschließen.

Jetzt werde ich eine bestimmte "Konvertierungsanomalie" demonstrieren:

# create dummy data.frame
d <- data.frame(char = letters[1:5], 
                fake_char = as.character(1:5), 
                fac = factor(1:5), 
                char_fac = factor(letters[1:5]), 
                num = 1:5, stringsAsFactors = FALSE)

Lassen Sie uns einen Blick darauf werfen data.frame

> d
  char fake_char fac char_fac num
1    a         1   1        a   1
2    b         2   2        b   2
3    c         3   3        c   3
4    d         4   4        d   4
5    e         5   5        e   5

und lass uns rennen:

> sapply(d, mode)
       char   fake_char         fac    char_fac         num 
"character" "character"   "numeric"   "numeric"   "numeric" 
> sapply(d, class)
       char   fake_char         fac    char_fac         num 
"character" "character"    "factor"    "factor"   "integer" 

Jetzt fragen Sie sich wahrscheinlich: "Wo ist eine Anomalie?" Nun, ich bin in R auf ziemlich eigenartige Dinge gestoßen, und das ist nicht die verwirrendste Sache, aber es kann Sie verwirren, besonders wenn Sie dies lesen, bevor Sie sich ins Bett rollen.

Hier geht's: Die ersten beiden Spalten sind character. Ich habe absichtlich 2 genannt nd ein fake_char. Erkennen Sie die Ähnlichkeit dieser characterVariablen mit einer, die Dirk in seiner Antwort erstellt hat. Es ist eigentlich ein numericalVektor, in den konvertiert wurde character. 3 rd und 4 th Spalte sind factor, und die letzte ist „rein“ numeric.

Wenn Sie die transformFunktion verwenden, können Sie die fake_charin numeric, aber nicht die charVariable selbst konvertieren .

> transform(d, char = as.numeric(char))
  char fake_char fac char_fac num
1   NA         1   1        a   1
2   NA         2   2        b   2
3   NA         3   3        c   3
4   NA         4   4        d   4
5   NA         5   5        e   5
Warning message:
In eval(expr, envir, enclos) : NAs introduced by coercion

Aber wenn Sie dasselbe tun fake_charund char_fac, haben Sie Glück und kommen ohne NA davon:

> transform(d, fake_char = as.numeric(fake_char), 
               char_fac = as.numeric(char_fac))

  char fake_char fac char_fac num
1    a         1   1        1   1
2    b         2   2        2   2
3    c         3   3        3   3
4    d         4   4        4   4
5    e         5   5        5   5

Wenn Sie transformiert speichern data.frameund nach modeund classsuchen, erhalten Sie:

> D <- transform(d, fake_char = as.numeric(fake_char), 
                    char_fac = as.numeric(char_fac))

> sapply(D, mode)
       char   fake_char         fac    char_fac         num 
"character"   "numeric"   "numeric"   "numeric"   "numeric" 
> sapply(D, class)
       char   fake_char         fac    char_fac         num 
"character"   "numeric"    "factor"   "numeric"   "integer"

Die Schlussfolgerung lautet also: Ja, Sie können einen characterVektor in einen numericEins konvertieren , aber nur, wenn seine Elemente in "konvertierbar" sind numeric. Wenn der characterVektor nur ein Element enthält, wird beim Versuch, diesen Vektor in numericaleinen zu konvertieren, eine Fehlermeldung angezeigt .

Und nur um meinen Standpunkt zu beweisen:

> err <- c(1, "b", 3, 4, "e")
> mode(err)
[1] "character"
> class(err)
[1] "character"
> char <- as.numeric(err)
Warning message:
NAs introduced by coercion 
> char
[1]  1 NA  3  4 NA

Und jetzt versuchen Sie nur zum Spaß (oder zum Üben), die Ausgabe dieser Befehle zu erraten:

> fac <- as.factor(err)
> fac
???
> num <- as.numeric(fac)
> num
???

Herzliche Grüße an Patrick Burns! =)


6
'stringsAsFactors = FALSE' ist wichtig beim Einlesen von Datendateien.
Robert Brisita

4
Ich weiß, das ist alt ... aber ... warum hast du transform () anstelle von df $ fake_char <- as.integer (df $ fake_char) gewählt? Es gibt mehrere Möglichkeiten, dieselbe Operation in R auszuführen, und ich verstehe die "richtige" Vorgehensweise nicht. Danke dir.
Ripvlan

Es ist also absolut unmöglich, err <- c (1, "b", 3, 4, "e") in einen numerischen Vektor umzuwandeln? In Excel gibt es eine Schaltfläche, mit der Sie "in Zahlen konvertieren" können. Machen Sie den Wert der Spalte zu einer Zahl. Ich versuche das in r nachzuahmen.
Flightless13wings

Warnung! = Fehler. Es wird kein Fehler beim Konvertieren von gemischten Zahlen / Zeichen in Zahlen angezeigt. Sie erhalten eine Warnung und einige NA-Werte.
Gregor Thomas

136

Etwas, das mir geholfen hat: Wenn Sie Bereiche von Variablen konvertieren müssen (oder nur mehrere), können Sie diese verwenden sapply.

Ein bisschen unsinnig, aber nur zum Beispiel:

data(cars)
cars[, 1:2] <- sapply(cars[, 1:2], as.factor)

Angenommen, die Spalten 3, 6-15 und 37 Ihres Datenrahmens müssen in einen numerischen konvertiert werden.

dat[, c(3,6:15,37)] <- sapply(dat[, c(3,6:15,37)], as.numeric)

1
as.factor im obigen Code macht das Spaltenzeichen
MySchizoBuddy

1
sapply ist besser als transformieren, wenn Vektoren von Indizes anstelle von Variablennamen behandelt werden
smci

@MySchizoBuddy ist korrekt, zumindest mit meinen Daten. Der ursprüngliche df übernimmt die "konvertierten" Spalten nicht als Faktoren. Sie werden Charakter bleiben. Wenn Sie den sapplyAnruf as.data.frame()auf der rechten Seite einbinden, wie unten von @Mehrad Mahmoudian vorgeschlagen, funktioniert es.
Knowah

Funktioniert das für eine Matrix? Ich versuche es mit genau dem gleichen Code, aber wenn ich die Klasse () einer Spalte danach überprüfe, steht immer noch "Zeichen" und nicht "numerisch"
namore

87

Wenn xder Spaltenname des Datenrahmens datund der Typfaktor xist, verwenden Sie:

as.numeric(as.character(dat$x))

3
Hinzufügen ist in der as.characterTat das, wonach ich gesucht habe. Andernfalls geht die Konvertierung manchmal schief. Zumindest in meinem Fall.
Thieme Hennis

1
Warum wird das Zeichen as.charakter benötigt? Ich bekam eine Fehlermeldung: Error: (list) object cannot be coerced to type 'double'obwohl ich mir ziemlich sicher war, dass mein Vektor keine Zeichen / Interpunktionen hatte. Dann habe ich es versucht as.numeric(as.character(dat$x))und es hat funktioniert. Jetzt bin ich mir nicht sicher, ob meine Spalte tatsächlich nur ganze Zahlen ist oder nicht!
Vagabund

2
Wenn Sie einen Faktor als numerisch festlegen, werden die Ebenen in numerische Werte konvertiert, nicht die tatsächlichen Werte. Daher wird as.character benötigt, um zuerst den Faktor in Zeichen und dann as.numeric umzuwandeln
MySchizoBuddy

Dies ist die beste Antwort hier
mitoRibo

25

Ich hätte einen Kommentar hinzugefügt (kann nicht niedrige Bewertung)

Nur um User276042 und Pangratz hinzuzufügen

dat$x = as.numeric(as.character(dat$x))

Dadurch werden die Werte der vorhandenen Spalte x überschrieben


16

Während Ihre Frage ausschließlich numerisch ist, gibt es viele Konvertierungen, die zu Beginn von R schwer zu verstehen sind. Ich werde mich mit Methoden befassen, um zu helfen. Diese Frage ähnelt dieser Frage .

Die Typkonvertierung kann ein Problem in R sein, da (1) Faktoren nicht direkt in numerische konvertiert werden können, sondern zuerst in die Zeichenklasse konvertiert werden müssen, (2) Daten ein Sonderfall sind, den Sie normalerweise separat behandeln müssen, und (3) Das Schleifen über Datenrahmenspalten kann schwierig sein. Glücklicherweise hat die "Tidyverse" die meisten Probleme gelöst.

Diese Lösung verwendet mutate_each(), um eine Funktion auf alle Spalten in einem Datenrahmen anzuwenden. In diesem Fall möchten wir die type.convert()Funktion anwenden , die Zeichenfolgen in numerische konvertiert, wo dies möglich ist. Weil R Faktoren liebt (nicht sicher warum), werden Zeichenspalten, die Zeichen bleiben sollen, in Faktor geändert. Um dies zu beheben, wird die mutate_if()Funktion verwendet, um Spalten zu erkennen, die Faktoren sind, und um das Zeichen zu ändern. Zuletzt wollte ich zeigen, wie Lubridate verwendet werden kann, um einen Zeitstempel in der Zeichenklasse auf Datum und Uhrzeit zu ändern, da dies auch für Anfänger häufig ein Haftblock ist.


library(tidyverse) 
library(lubridate)

# Recreate data that needs converted to numeric, date-time, etc
data_df
#> # A tibble: 5 × 9
#>             TIMESTAMP SYMBOL    EX  PRICE  SIZE  COND   BID BIDSIZ   OFR
#>                 <chr>  <chr> <chr>  <chr> <chr> <chr> <chr>  <chr> <chr>
#> 1 2012-05-04 09:30:00    BAC     T 7.8900 38538     F  7.89    523  7.90
#> 2 2012-05-04 09:30:01    BAC     Z 7.8850   288     @  7.88  61033  7.90
#> 3 2012-05-04 09:30:03    BAC     X 7.8900  1000     @  7.88   1974  7.89
#> 4 2012-05-04 09:30:07    BAC     T 7.8900 19052     F  7.88   1058  7.89
#> 5 2012-05-04 09:30:08    BAC     Y 7.8900 85053     F  7.88 108101  7.90

# Converting columns to numeric using "tidyverse"
data_df %>%
    mutate_all(type.convert) %>%
    mutate_if(is.factor, as.character) %>%
    mutate(TIMESTAMP = as_datetime(TIMESTAMP, tz = Sys.timezone()))
#> # A tibble: 5 × 9
#>             TIMESTAMP SYMBOL    EX PRICE  SIZE  COND   BID BIDSIZ   OFR
#>                <dttm>  <chr> <chr> <dbl> <int> <chr> <dbl>  <int> <dbl>
#> 1 2012-05-04 09:30:00    BAC     T 7.890 38538     F  7.89    523  7.90
#> 2 2012-05-04 09:30:01    BAC     Z 7.885   288     @  7.88  61033  7.90
#> 3 2012-05-04 09:30:03    BAC     X 7.890  1000     @  7.88   1974  7.89
#> 4 2012-05-04 09:30:07    BAC     T 7.890 19052     F  7.88   1058  7.89
#> 5 2012-05-04 09:30:08    BAC     Y 7.890 85053     F  7.88 108101  7.90

Beachten Sie, dass Sie den Befehl entfernen / vermeiden können , wenn Sie ihn mutate_all(type.convert, as.is=TRUE)anstelle von verwenden . ist ein Argument , das angibt, ob Zeichenfolgen als Zeichen oder als Faktoren konvertiert werden sollen. Standardmäßig konvertiert in (dh konvertiert Zeichenfolgen in Faktorklasse anstelle von Zeichenklasse). mutate_all(type.convert)mutate_if(is.factor, as.character)as.istype.convert()as.is=FALSEtype.convert()
LC-Datascientist

15

Tim hat recht und Shane hat eine Auslassung. Hier sind weitere Beispiele:

R> df <- data.frame(a = as.character(10:15))
R> df <- data.frame(df, num = as.numeric(df$a), 
                        numchr = as.numeric(as.character(df$a)))
R> df
   a num numchr
1 10   1     10
2 11   2     11
3 12   3     12
4 13   4     13
5 14   5     14
6 15   6     15
R> summary(df)
  a          num           numchr    
 10:1   Min.   :1.00   Min.   :10.0  
 11:1   1st Qu.:2.25   1st Qu.:11.2  
 12:1   Median :3.50   Median :12.5  
 13:1   Mean   :3.50   Mean   :12.5  
 14:1   3rd Qu.:4.75   3rd Qu.:13.8  
 15:1   Max.   :6.00   Max.   :15.0  
R> 

Wir haben data.framejetzt eine Zusammenfassung der Faktorspalte (Anzahl) und numerische Zusammenfassungen des as.numeric()--- was falsch ist, da es die numerischen Faktorstufen hat --- und die (korrekte) Zusammenfassung des as.numeric(as.character()).


1
Gern geschehen. Dies ist eine der albernsten Ecken der Sprache, und ich denke, sie wurde in der älteren Frage „R Gotchas“ hier erwähnt.
Dirk Eddelbuettel

14

Mit dem folgenden Code können Sie alle Datenrahmenspalten in numerische konvertieren (X ist der Datenrahmen, in den die Spalten konvertiert werden sollen):

as.data.frame(lapply(X, as.numeric))

und um die gesamte Matrix in eine numerische umzuwandeln, haben Sie zwei Möglichkeiten: Entweder:

mode(X) <- "numeric"

oder:

X <- apply(X, 2, as.numeric)

Alternativ können Sie die data.matrixFunktion verwenden, um alles in Zahlen umzuwandeln. Beachten Sie jedoch, dass die Faktoren möglicherweise nicht korrekt konvertiert werden. Daher ist es sicherer, alles characterzuerst in Folgendes zu konvertieren :

X <- sapply(X, as.character)
X <- data.matrix(X)

Normalerweise verwende ich diesen letzten, wenn ich gleichzeitig in Matrix und Numerisch konvertieren möchte


12

Wenn Sie auf Probleme stoßen mit:

as.numeric(as.character(dat$x))

Schauen Sie sich Ihre Dezimalstellen an. Wenn sie "," statt "sind." (zB "5,3") das oben genannte funktioniert nicht.

Eine mögliche Lösung ist:

as.numeric(gsub(",", ".", dat$x))

Ich glaube, dass dies in einigen nicht englischsprachigen Ländern durchaus üblich ist.


8

Universeller Weg mit type.convert()und rapply():

convert_types <- function(x) {
    stopifnot(is.list(x))
    x[] <- rapply(x, utils::type.convert, classes = "character",
                  how = "replace", as.is = TRUE)
    return(x)
}
d <- data.frame(char = letters[1:5], 
                fake_char = as.character(1:5), 
                fac = factor(1:5), 
                char_fac = factor(letters[1:5]), 
                num = 1:5, stringsAsFactors = FALSE)
sapply(d, class)
#>        char   fake_char         fac    char_fac         num 
#> "character" "character"    "factor"    "factor"   "integer"
sapply(convert_types(d), class)
#>        char   fake_char         fac    char_fac         num 
#> "character"   "integer"    "factor"    "factor"   "integer"

3
Dies ist die flexibelste Lösung - verdient einige positive Stimmen!
Richard Border

Sollte eine Top-Antwort sein. Entfernen as.is = TRUESie einfach, wenn Sie Ihren Charakter entweder in numerische oder in Faktoren umwandeln möchten
qfazille

Der Versuch, eine Reihe von Spalten in einem data.frame zu ändern, dessen Typ matrixdurch numerische Änderungen classes=matrixfehlerhaft ist. Das erste Argument muss vom Modus-Zeichen sein
add-semi-colons

1
Dies ist die beste Antwort im Thema.
Yuk

3

Um eine Datenrahmenspalte in eine numerische zu konvertieren, müssen Sie nur Folgendes tun: -

Faktor zu numerisch: -

data_frame$column <- as.numeric(as.character(data_frame$column))

Auch diese Antwort fügt dem aktuellen Satz von Antworten nichts hinzu. Es ist auch nicht die bevorzugte Methode, einen Faktor in einen numerischen Wert umzuwandeln. Den bevorzugten Weg finden Sie unter stackoverflow.com/q/3418128 .
BenBarnes

Eine bessere Antwort war:sapply(data_frame,function(x) as.numeric(as.character(x)))
Datenrahmen-gg

2

Obwohl andere das Thema ziemlich gut behandelt haben, möchte ich diesen zusätzlichen kurzen Gedanken / Hinweis hinzufügen. Mit regexp können Sie im Voraus prüfen, ob Zeichen möglicherweise nur aus Zahlen bestehen.

for(i in seq_along(names(df)){
     potential_numcol[i] <- all(!grepl("[a-zA-Z]",d[,i]))
}
# and now just convert only the numeric ones
d <- sapply(d[,potential_numcol],as.numeric)

Auf dieser wirklich schönen Website finden Sie anspruchsvollere reguläre Ausdrücke und einen guten Grund, warum Sie ihre Kraft lernen / erleben können: http://regexr.com/


1

In Anbetracht der Tatsache, dass möglicherweise Char-Spalten vorhanden sind, basiert dies auf @Abdou in Get- Spaltentypen von Excel- Tabellen. Antwort automatisch :

makenumcols<-function(df){
  df<-as.data.frame(df)
  df[] <- lapply(df, as.character)
  cond <- apply(df, 2, function(x) {
    x <- x[!is.na(x)]
    all(suppressWarnings(!is.na(as.numeric(x))))
  })
  numeric_cols <- names(df)[cond]
  df[,numeric_cols] <- sapply(df[,numeric_cols], as.numeric)
  return(df)
}
df<-makenumcols(df)

0

In meinem PC (R v.3.2.3) applyoder sapplygeben Sie einen Fehler. lapplyfunktioniert gut.

dt[,2:4] <- lapply(dt[,2:4], function (x) as.factor(as.numeric(x)))

0

Wenn der Datenrahmen mehrere Spaltentypen enthält, einige Zeichen, einige numerische, versuchen Sie Folgendes, um nur die Spalten, die numerische Werte enthalten, in numerische zu konvertieren:

for (i in 1:length(data[1,])){
  if(length(as.numeric(data[,i][!is.na(data[,i])])[!is.na(as.numeric(data[,i][!is.na(data[,i])]))])==0){}
  else {
    data[,i]<-as.numeric(data[,i])
  }
}

0

mit hablar :: convert

Um mehrere Spalten einfach in verschiedene Datentypen zu konvertieren, können Sie sie verwenden hablar::convert. Einfache Syntax: df %>% convert(num(a))Konvertiert die Spalte a von df in numerisch.

Detailliertes Beispiel

Konvertieren Sie alle Spalten von mtcarsin Zeichen.

df <- mtcars %>% mutate_all(as.character) %>% as_tibble()

> df
# A tibble: 32 x 11
   mpg   cyl   disp  hp    drat  wt    qsec  vs    am    gear  carb 
   <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
 1 21    6     160   110   3.9   2.62  16.46 0     1     4     4    
 2 21    6     160   110   3.9   2.875 17.02 0     1     4     4    
 3 22.8  4     108   93    3.85  2.32  18.61 1     1     4     1    

Mit hablar::convert:

library(hablar)

# Convert columns to integer, numeric and factor
df %>% 
  convert(int(cyl, vs),
          num(disp:wt),
          fct(gear))

Ergebnisse in:

# A tibble: 32 x 11
   mpg     cyl  disp    hp  drat    wt qsec     vs am    gear  carb 
   <chr> <int> <dbl> <dbl> <dbl> <dbl> <chr> <int> <chr> <fct> <chr>
 1 21        6  160    110  3.9   2.62 16.46     0 1     4     4    
 2 21        6  160    110  3.9   2.88 17.02     0 1     4     4    
 3 22.8      4  108     93  3.85  2.32 18.61     1 1     4     1    
 4 21.4      6  258    110  3.08  3.22 19.44     1 0     3     1   

0

Um ein Zeichen in ein numerisches Zeichen umzuwandeln, müssen Sie es durch Anwenden in einen Faktor umwandeln

BankFinal1 <- transform(BankLoan,   LoanApproval=as.factor(LoanApproval))
BankFinal1 <- transform(BankFinal1, LoanApp=as.factor(LoanApproval))

Sie müssen zwei Spalten mit denselben Daten erstellen, da eine Spalte nicht in numerische konvertiert werden kann. Wenn Sie eine Konvertierung durchführen, wird der folgende Fehler angezeigt

transform(BankData, LoanApp=as.numeric(LoanApproval))
Warning message:
  In eval(substitute(list(...)), `_data`, parent.frame()) :
  NAs introduced by coercion

Nachdem Sie dies getan haben, gelten zwei Spalten mit denselben Daten

BankFinal1 <- transform(BankFinal1, LoanApp      = as.numeric(LoanApp), 
                                    LoanApproval = as.numeric(LoanApproval))

Das Zeichen wird erfolgreich in numerisch umgewandelt


0

dfist Ihr Datenrahmen. xist eine Spalte, die dfSie konvertieren möchten

as.numeric(factor(df$x))

0

Wenn Sie die Faktoren nicht beibehalten möchten und sie auf eine Spalte anwenden möchten, die in eine numerische konvertiert werden kann, habe ich das folgende Skript verwendet. Wenn df Ihr ursprünglicher Datenrahmen ist, können Sie das folgende Skript verwenden.

df[] <- lapply(df, as.character)
df <- data.frame(lapply(df, function(x) ifelse(!is.na(as.numeric(x)), as.numeric(x),  x)))

Ich bezog mich übrigens auf die Lösung von Shane und Joran

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.