Làm thế nào để chuyển đổi một cột khung dữ liệu thành kiểu số?


261

Làm thế nào để bạn chuyển đổi một cột khung dữ liệu thành một loại số?

Câu trả lời:


267

Vì (vẫn) không ai có dấu kiểm, tôi cho rằng bạn có một số vấn đề thực tế trong đầu, chủ yếu là do bạn chưa chỉ định loại vectơ nào bạn muốn chuyển đổi sang numeric. Tôi đề nghị bạn nên áp dụng transformchức năng để hoàn thành nhiệm vụ của mình.

Bây giờ tôi sắp chứng minh một số "dị thường chuyển đổi" nhất định:

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

Chúng ta hãy lướt qua 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

và cho chúng tôi chạy:

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

Bây giờ bạn có thể tự hỏi mình "dị thường ở đâu?" Chà, tôi đã va vào những thứ khá kỳ dị ở R, và đây không phải điều khó hiểu nhất, nhưng nó có thể làm bạn bối rối, đặc biệt nếu bạn đọc điều này trước khi lăn vào giường.

Ở đây đi: hai cột đầu tiên là character. Tôi đã cố tình gọi là 2 thứ một fake_char. Phát hiện sự giống nhau của characterbiến này với biến mà Dirk đã tạo trong câu trả lời của mình. Nó thực sự là một numericalvector chuyển đổi thành character. 3 thứ 4 thứ cột là factor, và người cuối cùng là "thuần túy" numeric.

Nếu bạn sử dụng transformhàm, bạn có thể chuyển đổi fake_charthành numeric, nhưng không phải là charbiến.

> 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

nhưng nếu bạn làm điều tương tự fake_charchar_fac, bạn sẽ may mắn và thoát khỏi tình trạng không có 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

Nếu bạn lưu chuyển đổi data.framevà kiểm tra modeclass, bạn sẽ nhận được:

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

Vì vậy, kết luận là: Có, bạn có thể chuyển đổi charactervectơ thành một numeric, nhưng chỉ khi các phần tử của nó là "có thể chuyển đổi" thành numeric. Nếu chỉ có một characterphần tử trong vectơ, bạn sẽ gặp lỗi khi cố gắng chuyển đổi vectơ đó thành numericalmột phần tử.

Và chỉ để chứng minh quan điểm của tôi:

> 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

Và bây giờ, chỉ để giải trí (hoặc thực hành), hãy thử đoán đầu ra của các lệnh này:

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

Trân trọng kính chào Patrick Burns! =)


6
'StringAsFactors = FALSE' rất quan trọng khi đọc trong tệp dữ liệu.
Robert Brisita

4
Tôi biết điều này đã cũ ... nhưng ... tại sao bạn lại chọn biến đổi () trên df $ fake_char <- as.integer (df $ fake_char)? Có nhiều cách để thực hiện cùng một thao tác trong R và tôi gặp khó khăn khi hiểu cách làm "chính xác". Cảm ơn bạn.
ripvlan

Vì vậy, hoàn toàn không thể biến err <- c (1, "b", 3, 4, "e") thành một vectơ số? Trong excel, có một nút cho phép bạn "chuyển đổi thành số". làm cho bất cứ giá trị nào cột trở thành một số. Tôi đang cố gắng bắt chước điều đó trong r.
bay13wings

Cảnh báo! = Lỗi. Bạn không gặp lỗi khi chuyển đổi số / ký tự hỗn hợp thành số, bạn nhận được cảnh báo và một số giá trị NA.
Gregor Thomas

136

Một cái gì đó đã giúp tôi: nếu bạn có một loạt các biến để chuyển đổi (hoặc chỉ nhiều hơn một biến), bạn có thể sử dụng sapply.

Một chút vô nghĩa nhưng chỉ là ví dụ:

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

Giả sử các cột 3, 6-15 và 37 của khung dữ liệu của bạn cần được chuyển đổi thành số một có thể:

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

1
as.factor trong đoạn mã trên tạo ký tự cột
MySchizoBuddy

1
sapply tốt hơn biến đổi, khi xử lý các vectơ của chỉ số thay vì tên biến
smci

@MySchizoBuddy là chính xác, ít nhất là với dữ liệu của tôi. Các df ban đầu sẽ không lấy các cột "đã chuyển đổi" làm yếu tố; họ sẽ vẫn là nhân vật. Nếu bạn kết thúc sapplycuộc gọi ở as.data.frame()phía bên tay phải, như @Mehrad Mahmoudian đề xuất bên dưới, nó sẽ hoạt động.
biết

Điều này sẽ làm việc cho một ma trận? Tôi đang thử nó với cùng một mã, nhưng khi tôi kiểm tra lớp () của một cột sau đó, nó vẫn nói "ký tự" chứ không phải "số"
tên

87

if xlà tên cột của dataframe datxlà kiểu hệ số, hãy sử dụng:

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

3
thêm as.characterthực sự là những gì tôi đang tìm kiếm. Nếu không, việc chuyển đổi đôi khi gặp trục trặc. Ít nhất là trong trường hợp của tôi.
Thieme Hennis

1
Tại sao as.character cần thiết? Tôi đã nhận được một lỗi: Error: (list) object cannot be coerced to type 'double'mặc dù tôi khá chắc chắn rằng vectơ của tôi không có ký tự / dấu chấm câu. Sau đó tôi đã thử as.numeric(as.character(dat$x))và nó đã làm việc. Bây giờ tôi không chắc liệu cột của tôi trên thực tế chỉ có số nguyên hay không!
Vagabond

2
Nếu bạn thực hiện as.numeric thành một yếu tố, nó sẽ chuyển đổi các mức thành số chứ không phải giá trị thực. Do đó as.character là cần thiết trước tiên để chuyển đổi yếu tố thành nhân vật và sau đó là as.numeric
MySchizoBuddy

Đây là câu trả lời tốt nhất ở đây
mitoRibo

25

Tôi đã có thể thêm một bình luận (không thể đánh giá thấp)

Chỉ cần thêm vào user276042 và pangratz

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

Điều này sẽ ghi đè các giá trị của cột x hiện có


16

Mặc dù câu hỏi của bạn hoàn toàn đúng về số, có nhiều chuyển đổi rất khó hiểu khi bắt đầu R. Tôi sẽ nhắm đến các phương pháp để giải quyết. Câu hỏi này tương tự như Câu hỏi này .

Chuyển đổi loại có thể gây khó khăn cho R vì (1) các yếu tố không thể được chuyển đổi trực tiếp thành số, chúng cần được chuyển đổi thành lớp ký tự trước, (2) ngày là trường hợp đặc biệt mà bạn thường cần phải xử lý riêng và (3) lặp qua các cột khung dữ liệu có thể khó khăn. May mắn thay, "tidyverse" đã giải quyết hầu hết các vấn đề.

Giải pháp này sử dụng mutate_each()để áp dụng một hàm cho tất cả các cột trong khung dữ liệu. Trong trường hợp này, chúng tôi muốn áp dụng type.convert()hàm, chuyển đổi chuỗi thành số ở nơi có thể. Bởi vì R yêu thích các yếu tố (không chắc tại sao) các cột ký tự nên giữ nguyên ký tự được thay đổi thành yếu tố. Để khắc phục điều này, mutate_if()chức năng được sử dụng để phát hiện các cột là các yếu tố và thay đổi thành ký tự. Cuối cùng, tôi muốn chỉ ra làm thế nào có thể sử dụng Lubridate để thay đổi dấu thời gian trong lớp nhân vật thành thời gian vì đây cũng thường là một khối gắn bó cho người mới bắt đầu.


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

Lưu ý rằng nếu bạn sử dụng mutate_all(type.convert, as.is=TRUE)thay vì mutate_all(type.convert), bạn có thể xóa / tránh mutate_if(is.factor, as.character)để rút ngắn lệnh. as.islà một đối số trong type.convert()đó cho biết liệu nó nên chuyển đổi chuỗi dưới dạng ký tự hay dưới dạng các yếu tố. Theo mặc định, as.is=FALSEtrong type.convert()(nghĩa là chuyển đổi chuỗi thành lớp nhân tố thay vì lớp ký tự).
LC-datascientist

15

Tim là chính xác, và Shane có một thiếu sót. Dưới đây là các ví dụ bổ sung:

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.frameBây giờ chúng ta có một bản tóm tắt về cột yếu tố (tổng số) và tóm tắt số của as.numeric()--- sai vì nó có các mức yếu tố số --- và tóm tắt (chính xác) của as.numeric(as.character()).


1
Hân hạnh. Đây là một trong những góc ngớ ngẩn hơn của ngôn ngữ, và tôi nghĩ nó đặc trưng trong câu hỏi 'R Gotchas' cũ hơn ở đây.
Dirk Eddelbuettel

14

Với đoạn mã sau, bạn có thể chuyển đổi tất cả các cột của khung dữ liệu thành số (X là khung dữ liệu mà chúng tôi muốn chuyển đổi các cột của nó):

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

và để chuyển đổi toàn bộ ma trận thành số, bạn có hai cách: Hoặc:

mode(X) <- "numeric"

hoặc là:

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

Ngoài ra, bạn có thể sử dụng data.matrixchức năng để chuyển đổi mọi thứ thành số, mặc dù lưu ý rằng các yếu tố có thể không được chuyển đổi chính xác, vì vậy sẽ an toàn hơn khi chuyển đổi mọi thứ thành characterđầu tiên:

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

Tôi thường sử dụng cái cuối cùng này nếu tôi muốn chuyển đổi thành ma trận và số đồng thời


12

Nếu bạn gặp vấn đề với:

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

Hãy nhìn vào dấu thập phân của bạn. Nếu chúng là "," thay vì "." (ví dụ "5,3") ở trên sẽ không hoạt động.

Một giải pháp tiềm năng là:

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

Tôi tin rằng điều này khá phổ biến ở một số quốc gia không nói tiếng Anh.


8

Cách phổ quát sử dụng type.convert()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
Đây là giải pháp linh hoạt nhất - xứng đáng với một số upvote!
Richard Border

Nên là một câu trả lời hàng đầu. Chỉ cần xóa as.is = TRUEnếu bạn muốn chuyển đổi nhân vật của mình thành số hoặc yếu tố
qfazille

cố gắng thay đổi một loạt các cột trong data.frame có kiểu matrixthay đổi thành classes=matrixsố bị lỗi trong đối số đầu tiên phải có ký tự chế độ
add-semi-

1
Đây là câu trả lời tốt nhất trong chủ đề.
yuk

3

Để chuyển đổi cột khung dữ liệu thành số, bạn chỉ cần thực hiện: -

hệ số thành số: -

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

Một lần nữa, câu trả lời này không thêm bất cứ điều gì vào bộ câu trả lời hiện tại. Ngoài ra, đây không phải là cách ưa thích để chuyển đổi một yếu tố thành số. Xem stackoverflow.com/q 43218128 để biết cách ưa thích.
BenBarnes

Một câu trả lời tốt hơn là:sapply(data_frame,function(x) as.numeric(as.character(x)))
data-frame-gg

2

Mặc dù những người khác đã đề cập đến chủ đề này khá tốt, tôi muốn thêm ý nghĩ / gợi ý nhanh này. Bạn có thể sử dụng biểu thức chính quy để kiểm tra trước xem các ký tự có khả năng chỉ bao gồm số hay không.

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)

Để biết các biểu thức chính quy tinh vi hơn và gọn gàng tại sao để tìm hiểu / trải nghiệm sức mạnh của họ, hãy xem trang web thực sự tốt đẹp này: http://regexr.com/


1

Xem xét có thể tồn tại các cột char, điều này dựa trên @Abdou trong Lấy các loại cột của bảng excel tự động trả lời:

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

Trong PC của tôi (R v.3.2.3), applyhoặc sapplyđưa ra lỗi. lapplyhoạt động tốt

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

0

Nếu khung dữ liệu có nhiều loại cột, một số ký tự, một số số hãy thử cách sau để chuyển đổi chỉ các cột có chứa giá trị số thành số:

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

với hablar :: convert

Để dễ dàng chuyển đổi nhiều cột thành các loại dữ liệu khác nhau, bạn có thể sử dụng hablar::convert. Cú pháp đơn giản: df %>% convert(num(a))chuyển đổi cột a từ df sang số.

Ví dụ chi tiết

Cho phép chuyển đổi tất cả các cột của mtcarsnhân vật.

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    

Với hablar::convert:

library(hablar)

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

kết quả trong:

# 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

Để chuyển đổi ký tự thành số, bạn phải chuyển đổi nó thành yếu tố bằng cách áp dụng

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

Bạn phải tạo hai cột có cùng dữ liệu, vì một cột không thể chuyển đổi thành số. Nếu bạn thực hiện một chuyển đổi, nó sẽ báo lỗi dưới đây

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

vì vậy, sau khi thực hiện hai cột của cùng một dữ liệu

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

nó sẽ biến đổi ký tự thành số thành công


0

dfist dataframe của bạn. xlà một cột dfbạn muốn chuyển đổi

as.numeric(factor(df$x))

0

Nếu bạn không quan tâm đến việc bảo tồn các yếu tố và muốn áp dụng nó cho bất kỳ cột nào có thể được chuyển đổi thành số, tôi đã sử dụng tập lệnh bên dưới. nếu df là khung dữ liệu gốc của bạn, bạn có thể sử dụng tập lệnh bên dưới.

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

Tôi đã tham khảo giải pháp của ShaneJoran btw

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.