Jak przekonwertować kolumnę ramki danych na typ numeryczny?

Odpowiedzi:

267

Ponieważ (wciąż) nikt nie dostał znacznika wyboru, zakładam, że masz na myśli jakiś praktyczny problem, głównie dlatego, że nie określiłeś, jakiego rodzaju wektora chcesz przekonwertować numeric. Proponuję zastosować transformfunkcję w celu wykonania zadania.

Teraz zamierzam zademonstrować pewną „anomalię konwersji”:

# 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)

Rzućmy okiem na 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

i pozwól nam uruchomić:

> 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" 

Teraz prawdopodobnie zadajesz sobie pytanie „Gdzie jest anomalia?” Cóż, natknąłem się na dość osobliwe rzeczy w R i nie jest to najbardziej kłopotliwa sprawa, ale może cię to dezorientować, szczególnie jeśli przeczytasz to przed zjechaniem do łóżka.

Oto dwie pierwsze kolumny character. Ja celowo nazywane 2 nd jeden fake_char. Dostrzeż podobieństwo tej characterzmiennej do zmiennej, którą Dirk stworzył w swojej odpowiedzi. W rzeczywistości jest to numericalwektor przekonwertowany na character. 3 III i 4 p kolumny są factor, a ostatni jest „wyłącznie” numeric.

Jeśli korzystasz z transformfunkcji, możesz przekonwertować zmienną fake_charna numeric, ale nie charsamą zmienną.

> 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

ale jeśli zrobisz to samo na, fake_chari char_facbędziesz miał szczęście i nie będziesz mieć żadnych NA:

> 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

Jeśli zapiszesz przekształcone data.framei sprawdzisz modei class, otrzymasz:

> 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"

Wniosek jest następujący: Tak, możesz przekonwertować characterwektor na numericjeden, ale tylko wtedy, gdy jego elementy są „konwertowalne” na numeric. Jeśli characterw wektorze jest tylko jeden element, podczas próby konwersji tego wektora na numericaljeden wystąpi błąd .

I tylko, aby udowodnić mój punkt widzenia:

> 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

A teraz, dla zabawy (lub ćwiczenia), spróbuj odgadnąć wyjście tych poleceń:

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

Pozdrawiam Patrick Burns! =)

aL3xa
źródło
6
„stringsAsFactors = FALSE” jest ważne przy wczytywaniu plików danych.
Robert Brisita
4
Wiem, że to stare ... ale ... dlaczego wybrałeś transform () zamiast df $ fake_char <- as.integer (df $ fake_char)? Istnieje wiele sposobów wykonania tej samej operacji w języku R i utknąłem, rozumiejąc „prawidłowy” sposób jej wykonania. Dziękuję Ci.
ripvlan
Czy więc absolutnie niemożliwe jest przekształcenie err <- c (1, „b”, 3, 4, „e”) w wektor liczbowy? W programie Excel znajduje się przycisk, który umożliwia „konwersję na liczbę”. czyniąc dowolną wartość kolumną liczbą. Próbuję to naśladować w r.
flightless13wings
Ostrzeżenie! = Błąd. Nie pojawia się błąd podczas konwersji mieszanej cyfry / znaku na liczbę, pojawia się ostrzeżenie i niektóre wartości NA.
Gregor Thomas,
136

Coś, co mi pomogło: jeśli masz zakresy zmiennych do konwersji (lub tylko więcej niż jeden), możesz użyć sapply.

Trochę bezsensowne, ale tylko na przykład:

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

Powiedzmy, że kolumny 3, 6-15 i 37 twojej ramki danych muszą zostać przekonwertowane na numeryczne, że można:

dat[, c(3,6:15,37)] <- sapply(dat[, c(3,6:15,37)], as.numeric)
Sójka
źródło
1
as.factor w powyższym kodzie czyni znak kolumny
MySchizoBuddy
1
sapply jest lepszy niż transformacja, gdy obsługuje się wektory indeksów zamiast nazw zmiennych
smci
@MySchizoBuddy ma rację, przynajmniej z moimi danymi. Pierwotny plik df nie będzie przyjmował „przekonwertowanych” kolumn jako czynników; pozostaną postacią. Jeśli zawiniesz sapplypołączenie as.data.frame()po prawej stronie, jak sugerował poniżej @Mehrad Mahmoudian, zadziała.
knowah
Czy to zadziała dla matrycy? Próbuję tego z dokładnie tym samym kodem, ale kiedy sprawdzam klasę () kolumny później, nadal mówi „znak”, a nie „numeryczny”
namore
87

jeśli xjest nazwą kolumny ramki danych dati xjest typu, użyj:

as.numeric(as.character(dat$x))
pangratz
źródło
3
dodanie as.characterrzeczywiście było tym, czego szukałem. W przeciwnym razie konwersja czasami się nie powiedzie. Przynajmniej w moim przypadku.
Thieme Hennis
1
Dlaczego potrzebny jest znak as.character? Wystąpił błąd: Error: (list) object cannot be coerced to type 'double'chociaż byłem dość pewien, że mój wektor nie ma znaków / znaków interpunkcyjnych. Potem spróbowałem as.numeric(as.character(dat$x))i zadziałało. Teraz nie jestem pewien, czy moja kolumna jest w rzeczywistości tylko liczbami całkowitymi, czy nie!
włóczęga
2
Jeśli zrobisz to jako liczba. Czynnik przekształci poziomy na wartości liczbowe, a nie wartości rzeczywiste. Dlatego potrzebny jest as.character, aby najpierw przekonwertować czynnik na postać, a następnie as.numeric
MySchizoBuddy
To najlepsza odpowiedź tutaj
mitoRibo,
25

Dodałbym komentarz (niska ocena)

Wystarczy dodać na user276042 i pangratz

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

Spowoduje to zastąpienie wartości istniejącej kolumny x

Somum
źródło
16

Chociaż twoje pytanie dotyczy wyłącznie liczb, istnieje wiele konwersji, które trudno zrozumieć na początku R. Postaram się zająć metodami, które pomogą. To pytanie jest podobne do tego pytania .

Konwersja typów może być uciążliwa w R, ponieważ (1) czynników nie można bezpośrednio przekonwertować na wartości liczbowe, najpierw należy je przekonwertować na klasę znaków, (2) daty są szczególnym przypadkiem, z którym zwykle trzeba sobie poradzić osobno, i (3) zapętlanie kolumn kolumn danych może być trudne. Na szczęście „tidyverse” rozwiązało większość problemów.

W tym rozwiązaniu mutate_each()zastosowano funkcję do wszystkich kolumn w ramce danych. W tym przypadku chcemy zastosować type.convert()funkcję, która konwertuje ciągi znaków na wartości liczbowe tam, gdzie to możliwe. Ponieważ R uwielbia czynniki (nie wiem dlaczego) kolumny znaków, które powinny pozostać, zostaną zmienione na czynniki. Aby to naprawić, mutate_if()funkcja służy do wykrywania kolumn, które są czynnikami i zmieniają się w znak. Na koniec chciałem pokazać, jak można użyć lubridate, aby zmienić znacznik czasu w klasie postaci na datę i godzinę, ponieważ jest to często blokada dla początkujących.


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
Matt Dancho
źródło
Pamiętaj, że jeśli używasz mutate_all(type.convert, as.is=TRUE)zamiast mutate_all(type.convert), możesz usunąć / uniknąć, mutate_if(is.factor, as.character)aby skrócić polecenie. as.isjest argumentem type.convert()wskazującym, czy powinien konwertować ciągi znaków jako znaki, czy jako czynniki. Domyślnie as.is=FALSEin type.convert()(tzn. Konwertuje ciągi znaków na klasę współczynnika zamiast na klasę znaków).
LC-datascientist
15

Tim ma rację, a Shane ma pominięcie. Oto dodatkowe przykłady:

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> 

Nasz data.frameteraz ma podsumowanie kolumny czynników (liczby) i podsumowania liczbowe as.numeric()--- co jest nieprawidłowe, ponieważ ma poziomy liczbowe współczynników --- oraz (poprawne) podsumowanie as.numeric(as.character()).

Dirk Eddelbuettel
źródło
1
Cała przyjemność po mojej stronie. Jest to jeden z najgłupszych zakątków tego języka i myślę, że znalazł się tutaj w starszym pytaniu „R Gotchas”.
Dirk Eddelbuettel
14

Za pomocą następującego kodu możesz przekonwertować wszystkie kolumny ramek danych na wartości liczbowe (X to ramka danych, którą chcemy przekonwertować to kolumny):

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

a do konwersji całej macierzy na wartości liczbowe masz dwa sposoby: albo:

mode(X) <- "numeric"

lub:

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

Alternatywnie możesz użyć data.matrixfunkcji, aby przekonwertować wszystko na wartości liczbowe, chociaż pamiętaj, że czynniki mogą nie zostać poprawnie przekonwertowane, więc bezpieczniej jest przekonwertować wszystko na characternajpierw:

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

Zazwyczaj używam tego ostatniego, jeśli chcę jednocześnie przekonwertować na macierz i cyfrę

Mehrad Mahmoudian
źródło
12

Jeśli wystąpią problemy z:

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

Spójrz na swoje znaki dziesiętne. Jeśli są „,” zamiast „.” (np. „5,3”) powyższe nie będzie działać.

Potencjalnym rozwiązaniem jest:

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

Uważam, że jest to dość powszechne w niektórych krajach nieanglojęzycznych.

Gorka
źródło
8

Uniwersalny sposób za pomocą type.convert()i 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"
Artem Klevtsov
źródło
3
To najbardziej elastyczne rozwiązanie - zasługuje na aprobatę!
Richard Border
Powinna być najlepsza odpowiedź. Po prostu usuń, as.is = TRUEjeśli chcesz przekonwertować swoją postać na
liczbę
próba zmiany wiązki kolumn w pliku data.frame, który ma typ matrixna zmiany numeryczne, zignorowany classes=matrixpierwszy argument musi mieć postać trybu
dodaj średniki
1
To najlepsza odpowiedź w temacie.
Fuj
3

Aby przekonwertować kolumnę ramki danych na numeryczną, wystarczy:

współczynnik na wartość liczbową: -

data_frame$column <- as.numeric(as.character(data_frame$column))
Aayush Agrawal
źródło
Ponownie ta odpowiedź nie dodaje niczego do bieżącego zestawu odpowiedzi. Ponadto nie jest to preferowany sposób konwersji współczynnika na wartość liczbową. Preferowany sposób zobacz stackoverflow.com/q/3418128 .
BenBarnes,
Lepszą odpowiedzią było:sapply(data_frame,function(x) as.numeric(as.character(x)))
data-frame-gg
2

Chociaż inni dość dobrze omawiali ten temat, chciałbym dodać tę dodatkową szybką myśl / wskazówkę. Możesz użyć wyrażenia regularnego, aby z góry sprawdzić, czy znaki potencjalnie składają się tylko z cyfr.

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)

Bardziej wyrafinowane wyrażenia regularne i ciekawe, dlaczego warto uczyć się / doświadczać ich mocy, zobacz tę naprawdę fajną stronę internetową: http://regexr.com/

Matt Bannert
źródło
1

Biorąc pod uwagę, że mogą istnieć kolumny char, jest to oparte na @Abdou w Uzyskaj typy kolumn arkusza programu Excel automatycznie odpowiedz:

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)
Ferroao
źródło
0

Na moim komputerze (R v.3.2.3) applylub sapplypodaj błąd. lapplydziała dobrze.

dt[,2:4] <- lapply(dt[,2:4], function (x) as.factor(as.numeric(x)))
JKim
źródło
0

Jeśli ramka danych ma wiele typów kolumn, niektóre znaki, niektóre wartości liczbowe, spróbuj wykonać następujące czynności, aby przekonwertować tylko kolumny zawierające wartości liczbowe na wartości liczbowe:

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])
  }
}
Philipp
źródło
0

z hablar :: konwersją

Aby łatwo przekonwertować wiele kolumn na różne typy danych, których możesz użyć hablar::convert. Prosta składnia: df %>% convert(num(a))konwertuje kolumnę a z df na numeryczną.

Szczegółowy przykład

Pozwala przekonwertować wszystkie kolumny mtcarsna znak.

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    

Z hablar::convert:

library(hablar)

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

prowadzi do:

# 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   
davsjob
źródło
0

Aby przekonwertować znak na numeryczny, musisz go przekonwertować na współczynnik, stosując

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

Musisz utworzyć dwie kolumny z tymi samymi danymi, ponieważ jedna kolumna nie może zostać przekonwertowana na liczbę. Jeśli wykonasz jedną konwersję, pojawi się poniższy błąd

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

więc po wykonaniu dwóch kolumn tych samych danych stosuje się

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

z powodzeniem przekształci znak w numeryczny

jadhav suraj
źródło
0

dfistnieje twoja ramka danych. xto kolumna, dfktórą chcesz przekonwertować

as.numeric(factor(df$x))
Justin Lange
źródło
0

Jeśli nie zależy ci na zachowaniu czynników i chcesz zastosować je do dowolnej kolumny, którą można przekonwertować na wartości liczbowe, skorzystałem ze skryptu poniżej. jeśli df jest twoją oryginalną ramką danych, możesz użyć skryptu poniżej.

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

I odwołuje Shane'a and Jøran za rozwiązanie btw

Michael Kassa
źródło