Bagaimana cara mengubah kolom bingkai data ke tipe numerik?

261

Bagaimana Anda mengonversi kolom bingkai data ke tipe numerik?

akroa
sumber

Jawaban:

267

Karena (masih) tidak ada yang mendapat tanda centang, saya berasumsi bahwa Anda memiliki beberapa masalah praktis dalam pikiran, terutama karena Anda belum menentukan jenis vektor apa yang ingin Anda konversi numeric. Saya sarankan Anda harus menerapkan transformfungsi untuk menyelesaikan tugas Anda.

Sekarang saya akan menunjukkan "anomali konversi" tertentu:

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

Mari kita melirik 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

dan mari kita jalankan:

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

Sekarang Anda mungkin bertanya pada diri sendiri, "Di mana anomali itu?" Yah, saya telah bertemu dengan hal-hal yang sangat aneh di R, dan ini bukan hal yang paling membingungkan, tetapi itu dapat membingungkan Anda, terutama jika Anda membaca ini sebelum berguling ke tempat tidur.

Ini dia: dua kolom pertama adalah character. Saya sengaja menelepon nomor dua fake_char. Temukan kesamaan charactervariabel ini dengan variabel yang dibuat Dirk dalam jawabannya. Ini sebenarnya sebuah numericalvektor yang dikonversi menjadi character. 3 rd dan 4 th kolom yang factor, dan yang terakhir adalah "murni" numeric.

Jika Anda menggunakan transformfungsi, Anda bisa mengubahnya fake_charmenjadi numeric, tetapi bukan charvariabel itu sendiri.

> 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

tetapi jika Anda melakukan hal yang sama fake_chardan char_fac, Anda akan beruntung, dan lolos tanpa 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

Jika Anda menyimpan transformasi data.framedan memeriksa modedan class, Anda akan mendapatkan:

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

Jadi, kesimpulannya adalah: Ya, Anda dapat mengubah charactervektor menjadi numericsatu, tetapi hanya jika elemen-elemennya "dapat dikonversi" numeric. Jika hanya ada satu characterelemen dalam vektor, Anda akan mendapatkan kesalahan ketika mencoba mengubah vektor itu menjadi numericalsatu.

Dan hanya untuk membuktikan maksud saya:

> 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

Dan sekarang, hanya untuk bersenang-senang (atau berlatih), coba tebak output dari perintah ini:

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

Salam untuk Patrick Burns! =)

aL3xa
sumber
6
'stringsAsFactors = FALSE' penting untuk ketika membaca dalam file data.
Robert Brisita
4
Saya tahu ini sudah tua ... tapi ... mengapa Anda memilih transform () lebih dari df $ fake_char <- as.integer (df $ fake_char)? Ada beberapa cara untuk melakukan operasi yang sama di R dan saya terjebak memahami cara yang "benar" melakukannya. Terima kasih.
ripvlan
Jadi benar-benar mustahil untuk mengubah err <- c (1, "b", 3, 4, "e") menjadi vektor numerik? Di excel, ada tombol yang memungkinkan Anda untuk "mengkonversi ke nomor". membuat nilai kolom apa pun menjadi numerik. Saya mencoba untuk meniru itu di r.
flightless13wings
Peringatan! = Kesalahan. Anda tidak mendapatkan kesalahan saat mengonversi angka / karakter campuran menjadi angka, Anda mendapatkan peringatan dan beberapa nilai NA.
Gregor Thomas
136

Sesuatu yang telah membantu saya: jika Anda memiliki rentang variabel untuk dikonversi (atau lebih dari satu), Anda dapat menggunakannya sapply.

Agak tidak masuk akal tetapi hanya sebagai contoh:

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

Katakanlah kolom 3, 6-15 dan 37 dari Anda dataframe perlu dikonversi menjadi numerik yang bisa:

dat[, c(3,6:15,37)] <- sapply(dat[, c(3,6:15,37)], as.numeric)
Jay
sumber
1
as.factor dalam kode di atas membuat karakter kolom
MySchizoBuddy
1
sapply lebih baik daripada mentransformasi, ketika menangani vektor indeks daripada nama variabel
smci
@MySchizoBuddy benar, setidaknya dengan data saya. Df asli tidak akan mengambil kolom "dikonversi" sebagai faktor; mereka akan tetap menjadi karakter. Jika Anda membungkus sapplypanggilan di as.data.frame()sisi kanan, seperti yang disarankan @Mehrad Mahmoudian di bawah ini, itu akan berfungsi.
Knowah
Apakah ini akan bekerja untuk sebuah matriks? Saya mencoba dengan kode yang sama persis, namun ketika saya memeriksa kelas () kolom setelahnya, masih tertulis "karakter" dan bukan "numerik"
namore
87

jika xadalah nama kolom dari dataframe dat, dan xmerupakan tipe faktor, gunakan:

as.numeric(as.character(dat$x))
pangratz
sumber
3
menambahkan as.charactermemang apa yang saya cari. Kalau tidak, konversi terkadang salah. Setidaknya dalam kasus saya.
Thieme Hennis
1
Mengapa bakteri as diperlukan? Saya mendapatkan kesalahan: Error: (list) object cannot be coerced to type 'double'meskipun saya cukup yakin bahwa vektor saya tidak memiliki karakter / tanda baca. Kemudian saya mencoba as.numeric(as.character(dat$x))dan berhasil. Sekarang saya tidak yakin apakah kolom saya sebenarnya hanya bilangan bulat atau tidak!
vagabond
2
Jika Anda melakukan as.numeric ke suatu faktor itu akan mengkonversi level menjadi numerik bukan nilai aktual. Karenanya as.character diperlukan untuk mengubah faktor menjadi karakter dan kemudian sebagai.numerik
MySchizoBuddy
Ini adalah jawaban terbaik di sini
mitoRibo
25

Saya akan menambahkan komentar (tidak boleh peringkat rendah)

Hanya untuk menambahkan pada user276042 dan pangratz

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

Ini akan menimpa nilai kolom yang ada x

Somum
sumber
16

Meskipun pertanyaan Anda benar-benar numerik, ada banyak konversi yang sulit dipahami ketika memulai R. Saya akan berupaya membahas metode untuk membantu. Pertanyaan ini mirip dengan Pertanyaan Ini .

Konversi jenis dapat menjadi masalah di R karena (1) faktor tidak dapat dikonversi langsung ke numerik, mereka perlu dikonversi ke kelas karakter terlebih dahulu, (2) tanggal adalah kasus khusus yang biasanya perlu Anda tangani secara terpisah, dan (3) perulangan di kolom bingkai data bisa rumit. Untungnya, "tidyverse" telah menyelesaikan sebagian besar masalah.

Solusi ini digunakan mutate_each()untuk menerapkan fungsi ke semua kolom dalam bingkai data. Dalam hal ini, kami ingin menerapkan type.convert()fungsi, yang mengubah string menjadi numerik di mana ia bisa. Karena R menyukai faktor (tidak yakin mengapa) kolom karakter yang harus tetap karakter diubah menjadi faktor. Untuk memperbaikinya, mutate_if()fungsi ini digunakan untuk mendeteksi kolom yang merupakan faktor dan berubah menjadi karakter. Terakhir, saya ingin menunjukkan bagaimana lubridate dapat digunakan untuk mengubah stempel waktu di kelas karakter ke waktu-tanggal karena ini juga sering merupakan blok yang sulit bagi pemula.


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
sumber
Perhatikan bahwa jika Anda menggunakan mutate_all(type.convert, as.is=TRUE)alih-alih mutate_all(type.convert), Anda dapat menghapus / menghindari mutate_if(is.factor, as.character)untuk mempersingkat perintah. as.isadalah argumen type.convert()yang menunjukkan apakah string harus dikonversi sebagai karakter atau sebagai faktor. Secara default, as.is=FALSEdi type.convert()(mis., Mengonversi string ke kelas faktor alih-alih kelas karakter).
LC-datacientist
15

Tim sudah benar, dan Shane memiliki kekurangan. Berikut adalah contoh tambahan:

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> 

data.frameSekarang kami memiliki ringkasan kolom faktor (jumlah) dan ringkasan numerik dari as.numeric()--- yang salah karena mendapat tingkat faktor numerik --- dan ringkasan (yang benar) dari as.numeric(as.character()).

Dirk Eddelbuettel
sumber
1
Dengan senang hati. Ini adalah salah satu sudut bahasa yang lebih konyol, dan saya pikir itu ditampilkan dalam pertanyaan 'R Gotchas' yang lebih tua di sini.
Dirk Eddelbuettel
14

Dengan kode berikut Anda dapat mengonversi semua kolom bingkai data menjadi numerik (X adalah bingkai data yang ingin Anda konversi kolomnya):

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

dan untuk mengubah seluruh matriks menjadi numerik Anda memiliki dua cara: Baik:

mode(X) <- "numeric"

atau:

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

Sebagai alternatif, Anda dapat menggunakan data.matrixfungsi untuk mengubah segalanya menjadi numerik, meskipun perlu diingat bahwa faktor-faktor tersebut mungkin tidak dapat dikonversi dengan benar, jadi lebih aman untuk mengonversi semuanya menjadi yang characterpertama:

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

Saya biasanya menggunakan yang terakhir ini jika saya ingin mengkonversi ke matriks dan angka secara bersamaan

Mehrad Mahmoudian
sumber
12

Jika Anda mengalami masalah dengan:

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

Lihatlah tanda desimal Anda. Jika mereka "," bukannya "." (mis. "5,3") di atas tidak akan berfungsi.

Solusi potensial adalah:

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

Saya percaya ini sangat umum di beberapa negara yang tidak berbahasa Inggris.

Gorka
sumber
8

Cara universal menggunakan type.convert()dan 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
sumber
3
Ini adalah solusi yang paling fleksibel - layak mendapatkan beberapa peningkatan!
Richard Border
Harus menjadi jawaban teratas. Hapus saja as.is = TRUEjika Anda ingin mengonversi karakter Anda menjadi angka atau faktor
qfazille
mencoba mengubah banyak kolom dalam data.frame yang memiliki tipe matrixke perubahan numerik yang salah classes=matrixargumen pertama harus dari karakter mode
add-semi-titik dua
1
Ini adalah jawaban terbaik dalam topik ini.
yuk
3

Untuk mengonversi kolom bingkai data menjadi numerik, Anda cukup melakukan: -

faktor numerik: -

data_frame$column <- as.numeric(as.character(data_frame$column))
Aayush Agrawal
sumber
Sekali lagi, jawaban ini tidak menambahkan apa pun ke set jawaban saat ini. Juga, ini bukan cara yang disukai untuk mengubah faktor menjadi angka. Lihat stackoverflow.com/q/3418128 untuk cara yang disukai.
BenBarnes
Jawaban yang lebih baik adalah:sapply(data_frame,function(x) as.numeric(as.character(x)))
data-frame-gg
2

Meskipun orang lain telah membahas topik dengan cukup baik, saya ingin menambahkan pemikiran / petunjuk cepat tambahan ini. Anda dapat menggunakan regexp untuk memeriksa terlebih dahulu apakah karakter yang berpotensi hanya terdiri dari angka.

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)

Untuk ekspresi reguler yang lebih canggih dan alasan yang bagus untuk mempelajari / merasakan kekuatan mereka, lihat situs web yang sangat bagus ini: http://regexr.com/

Matt Bannert
sumber
1

Mengingat mungkin ada kolom char, ini didasarkan pada @Abdou di Dapatkan jenis lembar excel secara otomatis menjawab:

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
sumber
0

Di PC saya (R v.3.2.3), applyatau sapplyberikan kesalahan. lapplybekerja dengan baik.

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

Jika kerangka data memiliki beberapa jenis kolom, beberapa karakter, beberapa numerik coba yang berikut ini untuk mengonversi hanya kolom yang berisi nilai numerik ke angka:

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
sumber
0

dengan hablar :: convert

Untuk dengan mudah mengonversi banyak kolom ke berbagai tipe data yang dapat Anda gunakan hablar::convert. Sintaks sederhana: df %>% convert(num(a))mengonversi kolom a dari df ke numerik.

Contoh terperinci

Mari kita konversi semua kolom mtcarsmenjadi karakter.

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    

Dengan hablar::convert:

library(hablar)

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

menghasilkan:

# 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
sumber
0

Untuk mengkonversi karakter ke numerik Anda harus mengubahnya menjadi faktor dengan menerapkan

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

Anda harus membuat dua kolom dengan data yang sama, karena satu kolom tidak dapat dikonversi menjadi angka. Jika Anda melakukan satu konversi itu memberikan kesalahan di bawah ini

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

jadi, setelah melakukan dua kolom data yang sama berlaku

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

itu akan berhasil mengubah karakter menjadi numerik

jadhav suraj
sumber
0

dfist dataframe Anda. xadalah kolom dfyang ingin Anda konversi

as.numeric(factor(df$x))
Justin Lange
sumber
0

Jika Anda tidak peduli tentang menjaga faktor-faktor, dan ingin menerapkannya ke kolom apa pun yang dapat dikonversi menjadi numerik, saya menggunakan skrip di bawah ini. jika df adalah kerangka data asli Anda, Anda dapat menggunakan skrip di bawah ini.

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

Saya mereferensikan solusi Shane dan Joran btw

Michael Kassa
sumber