Jak przekonwertować kolumnę ramki danych na typ numeryczny?

Jak przekonwertować kolumnę ramki danych na typ liczbowy?

Author: Artem Klevtsov, 2010-02-18

18 answers

Ponieważ (nadal) nikt nie otrzymał znacznika wyboru, zakładam, że masz jakiś praktyczny problem na myśli, głównie dlatego, że nie określiłeś, jaki typ wektora chcesz przekonwertować na numeric. Sugeruję, abyś zastosował transform funkcję, aby wykonać swoje zadanie.

Teraz zademonstruję 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 biegnijmy:

> 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 pewnie zadajesz sobie pytanie " gdzie jest anomalia?"Cóż, wpadłem na dość osobliwe rzeczy w R, i to nie jest najbardziej myląca rzecz, ale może cię zmylić, zwłaszcza jeśli przeczytasz to przed położeniem się do łóżka.

Zaczyna się: pierwsze dwie kolumny to character. Celowo nazwałem 2 nd jeden fake_char. Zauważ podobieństwo tej zmiennej character do tej, którą Dirk stworzył w swojej odpowiedzi. Jest to wektor numerical zamieniony na character. 3rd i 4TH kolumny to factor, a ostatni to "czysto" numeric.

Jeśli użyjesz funkcji transform, możesz przekonwertować fake_char na numeric, ale nie samą zmienną char.

> 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_char i char_fac, będziesz miał szczęście i ujdzie ci to na sucho:

> 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 data.frame i sprawdzisz mode i 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"

Więc wniosek jest: tak, można przekonwertować character wektor na numeric jeden, ale tylko wtedy, gdy są to elementy są "convertible" do numeric. jeśli jest tylko jeden character element w wektorze, pojawi się błąd podczas próby przekonwertowania tego wektora na numerical jeden.

I tylko dla udowodnienia mojej racji:

> 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 praktyki), spróbuj odgadnąć wynik tych poleceń:]}
> fac <- as.factor(err)
> fac
???
> num <- as.numeric(fac)
> num
???
Pozdrawiam Patricka Burnsa! =)
 284
Author: aL3xa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-19 00:31:30

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 ramki danych muszą być przekonwertowane na liczbowe:

dat[, c(3,6:15,37)] <- sapply(dat[, c(3,6:15,37)], as.numeric)
 143
Author: Jay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-06 22:45:56

Jeśli x jest nazwą kolumny ramki danych dat, a x jest czynnikiem typu, użyj:

as.numeric(as.character(dat$x))
 90
Author: pangratz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-22 08:54:30

Dodałbym komentarz (cant niska ocena)

Wystarczy dodać na user276042 i pangratz

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

To nadpisze wartości istniejącej kolumny x

 29
Author: Somum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-06 05:58:06

Podczas gdy twoje pytanie jest ściśle numeryczne, istnieje wiele konwersji, które są trudne do zrozumienia podczas rozpoczynania R. postaram się zająć metodami, które pomogą. To pytanie jest podobne do tego pytania .

Konwersja typu może być uciążliwa w R, ponieważ (1) współczynniki nie mogą być przekonwertowane bezpośrednio na liczbę, muszą być najpierw przekonwertowane na klasę znaków, (2) daty są szczególnym przypadkiem, z którym zazwyczaj trzeba sobie poradzić osobno, oraz (3) zapętlanie kolumn ramki danych to może być trudne. Na szczęście "tidyverse" rozwiązał większość problemów.

To rozwiązanie wykorzystuje mutate_each() do zastosowania funkcji do wszystkich kolumn w ramce danych. W tym przypadku chcemy zastosować funkcję type.convert(), która zamienia ciągi znaków na liczbowe, gdzie może. Ponieważ r loves factors (Nie wiem dlaczego) kolumny znaków, które powinny pozostać znakami, zostają zmienione na factor. Aby to naprawić, funkcja mutate_if() jest używana do wykrywania kolumn, które są czynnikami i zmiany na znak. Na koniec chciałem pokazać jak lubridate może być użyty do zmiany znacznika czasu w klasie character na date-time, ponieważ często jest to blok 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
 18
Author: Matt Dancho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-24 23:45:07

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.frame ma teraz podsumowanie kolumny czynnika (liczy) i podsumowania numeryczne as.numeric() - - - co jest błędne , ponieważ ma poziomy współczynników numerycznych --- i (poprawne) podsumowanie as.numeric(as.character()).

 15
Author: Dirk Eddelbuettel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-06 22:51:41

Za pomocą poniższego kodu można przekonwertować wszystkie kolumny ramki danych na cyfry (X jest ramką danych, którą chcemy przekonwertować):

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

A do konwersji całej macierzy na liczbową masz dwa sposoby: Albo:

mode(X) <- "numeric"

Lub:

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

Alternatywnie możesz użyć funkcji data.matrix do konwersji wszystkiego na liczbę, chociaż pamiętaj, że czynniki mogą nie zostać przekonwertowane poprawnie, więc bezpieczniej jest najpierw przekonwertować wszystko na character:

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

Zwykle użyj tej ostatniej Jeśli chcę konwertować jednocześnie na macierz i cyfrę

 15
Author: Mehrad Mahmoudian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-04 10:34:35

Jeśli napotkasz 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 zadziała.

Rozwiązaniem potencjalnym jest:

as.numeric(gsub(",", ".", dat$x))
Uważam, że jest to dość powszechne w niektórych krajach nieangielskojęzycznych.
 14
Author: Gorka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-15 14:12:13

Sposób uniwersalny 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"
 10
Author: Artem Klevtsov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-10 05:35:29

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

Współczynnik do liczb:-

data_frame$column <- as.numeric(as.character(data_frame$column))
 3
Author: Aayush Agrawal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-18 07:25:01

Chociaż inni dość dobrze omówili ten temat, chciałbym dodać tę dodatkową szybką myśl / podpowiedź. Możesz użyć wyrażenia regularnego, aby sprawdzić z góry, 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)

Dla bardziej wyrafinowanych wyrażeń regularnych i zgrabny dlaczego uczyć się/doświadczyć ich mocy zobaczyć tę naprawdę fajną stronę: http://regexr.com/

 2
Author: Matt Bannert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-22 09:58:44

Biorąc pod uwagę, że mogą istnieć kolumny znaków, jest to oparte na @Abdou w Automatycznie pobieraj typy kolumn arkusza excel odpowiedź:

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)
 1
Author: Ferroao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-04 21:31:00

W moim PC (R v. 3.2.3), apply lub sapply Podaj błąd. Działa dobrze.

dt[,2:4] <- lapply(dt[,2:4], function (x) as.factor(as.numeric(x)))
 0
Author: JKim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-11 05:53:10

Jeśli ramka danych ma wiele typów kolumn, niektóre znaki, niektóre liczby, spróbuj wykonać następujące czynności, aby przekonwertować tylko kolumny zawierające wartości liczbowe na 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])
  }
}
 0
Author: Philipp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-11 22:08:26

Z hablar:: convert

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

Szczegółowy przykład

Pozwala skonwertować wszystkie kolumny mtcars na 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))

Wyniki w:

# 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
Author: davsjob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-04 11:02:14

Aby przekonwertować znak na cyfrę, musisz przekonwertować go na współczynnik przez zastosowanie

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ę, wyświetli 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 Zastosuj

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

Pomyślnie przetworzy znak na cyfrę

 0
Author: jadhav suraj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-17 21:05:30

df to twoja ramka danych. x jest kolumną df chcesz przekonwertować

as.numeric(factor(df$x))
 0
Author: Justin Lange,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-12-04 17:41:59

Jeśli nie zależy ci na zachowaniu czynników i chcesz zastosować je do dowolnej kolumny, która może zostać przekonwertowana na liczbę, użyłem poniższego skryptu. jeśli df jest twoją oryginalną ramką danych, możesz użyć poniższego skryptu.

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

Odwołałem się do Shane 's i Joran' S rozwiązanie btw

 0
Author: Michael Kassa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-19 02:45:18