Ketika saya mengubah faktor numerik atau integer, saya mendapatkan tingkat dasar kode, bukan nilai-nilai dalam angka.
f <- factor(sample(runif(5), 20, replace = TRUE))
## [1] 0.0248644019011408 0.0248644019011408 0.179684827337041
## [4] 0.0284090070053935 0.363644931698218 0.363644931698218
## [7] 0.179684827337041 0.249704354675487 0.249704354675487
## [10] 0.0248644019011408 0.249704354675487 0.0284090070053935
## [13] 0.179684827337041 0.0248644019011408 0.179684827337041
## [16] 0.363644931698218 0.249704354675487 0.363644931698218
## [19] 0.179684827337041 0.0284090070053935
## 5 Levels: 0.0248644019011408 0.0284090070053935 ... 0.363644931698218
as.numeric(f)
## [1] 1 1 3 2 5 5 3 4 4 1 4 2 3 1 3 5 4 5 3 2
as.integer(f)
## [1] 1 1 3 2 5 5 3 4 4 1 4 2 3 1 3 5 4 5 3 2
Aku harus resor untuk paste
untuk mendapatkan nilai-nilai yang nyata:
as.numeric(paste(f))
## [1] 0.02486440 0.02486440 0.17968483 0.02840901 0.36364493 0.36364493
## [7] 0.17968483 0.24970435 0.24970435 0.02486440 0.24970435 0.02840901
## [13] 0.17968483 0.02486440 0.17968483 0.36364493 0.24970435 0.36364493
## [19] 0.17968483 0.02840901
Apakah ada cara yang lebih baik untuk mengkonversi faktor numerik?
Lihat bagian Peringatan dari ?faktor
:
khususnya,
sebagai.numerik
diterapkan untuk faktor ini tidak berarti, dan mungkin terjadi secara implisit paksaan. Untuk mengubah faktorf
untuk sekitar aslinya numerik nilai-nilai,sebagai.numerik(tingkat(f))[f]
adalah direkomendasikan dan sedikit lebih efisien daripadasebagai.numerik(seperti.karakter(f))
.
FAQ di R memiliki saran yang sama.
Mengapa sebagai.numerik(tingkat(f))[f]
lebih efisien dari.numerik(seperti.karakter(f))
?
sebagai.numerik(seperti.karakter(f))
lebih efektif sebagai.numerik(tingkat(f)[f])
, sehingga anda melakukan konversi numerik pada panjang (x)
nilai-nilai, bukan pada nlevels(x)
nilai-nilai. Perbedaan kecepatan akan menjadi yang paling jelas untuk panjang vektor dengan beberapa tingkat. Jika nilai-nilai sebagian besar adalah unik, tidak ada't akan banyak perbedaan dalam kecepatan. Namun anda melakukan konversi, operasi ini mungkin menjadi hambatan dalam kode anda, jadi don't khawatir terlalu banyak tentang hal itu.
Beberapa timing
library(microbenchmark)
microbenchmark(
as.numeric(levels(f))[f],
as.numeric(levels(f)[f]),
as.numeric(as.character(f)),
paste0(x),
paste(x),
times = 1e5
)
## Unit: microseconds
## expr min lq mean median uq max neval
## as.numeric(levels(f))[f] 3.982 5.120 6.088624 5.405 5.974 1981.418 1e+05
## as.numeric(levels(f)[f]) 5.973 7.111 8.352032 7.396 8.250 4256.380 1e+05
## as.numeric(as.character(f)) 6.827 8.249 9.628264 8.534 9.671 1983.694 1e+05
## paste0(x) 7.964 9.387 11.026351 9.956 10.810 2911.257 1e+05
## paste(x) 7.965 9.387 11.127308 9.956 11.093 2419.458 1e+05
R memiliki jumlah (undocumented) kenyamanan fungsi untuk mengkonversi faktor-faktor:
as.karakter.faktor
as.data.frame.faktor
as.Tanggal.faktor
as.daftar.faktor
as.vektor.faktor
Tapi mengganggu, tidak ada yang lebih untuk menangani faktor -> numerik konversi. Sebagai perpanjangan dari Joshua Ulrich's jawaban, saya akan menyarankan untuk mengatasi kelalaian ini dengan definisi anda sendiri idiomatik fungsi:
as.numeric.factor <- function(x) {as.numeric(levels(x))[x]}
yang dapat anda simpan pada awal naskah, atau bahkan lebih baik anda .Rprofile
file.
Cara yang paling mudah adalah dengan menggunakan unfactor
fungsi dari paket varhandle
unfactor(your_factor_variable)
Contoh ini dapat menjadi awal yang cepat:
x <- rep(c("a", "b", "c"), 20)
y <- rep(c(1, 1, 0), 20)
class(x) # -> "character"
class(y) # -> "numeric"
x <- factor(x)
y <- factor(y)
class(x) # -> "factor"
class(y) # -> "factor"
library(varhandle)
x <- unfactor(x)
y <- unfactor(y)
class(x) # -> "character"
class(y) # -> "numeric"
Catatan: ini jawaban tertentu yang tidak untuk mengkonversi angka-dihargai faktor numerik, itu adalah untuk mengkonversi kategoris faktor untuk mereka sesuai tingkat angka.
Setiap jawaban dalam posting ini gagal untuk menghasilkan hasil bagi saya , NAs mendapatkan dihasilkan.
y2<-factor(c("A","B","C","D","A"));
as.numeric(levels(y2))[y2]
[1] NA NA NA NA NA Warning message: NAs introduced by coercion
Apa yang bekerja untuk saya adalah ini -
as.integer(y2)
# [1] 1 2 3 4 1
Hal ini dimungkinkan hanya dalam kasus ketika faktor label sesuai dengan nilai-nilai asli. Saya akan menjelaskannya dengan contoh.
Asumsikan data vektor x
:
x <- c(20, 10, 30, 20, 10, 40, 10, 40)
Sekarang saya akan membuat satu faktor dengan empat label:
f <- factor(x, levels = c(10, 20, 30, 40), labels = c("A", "B", "C", "D"))
x
adalah dengan tipe double, f
adalah dengan tipe integer. Ini adalah pertama tidak dapat dihindari hilangnya informasi. Faktor-faktor yang selalu disimpan sebagai bilangan bulat.> typeof(x)
[1] "double"
> typeof(f)
[1] "integer"
f
yang tersedia. Kita dapat melihat bahwa f
hanya menampung nilai integer 1, 2, 3, 4, dan dua atribut - daftar label ("A", "B", "C", "D") dan kelas atribut "faktor". Ada yang lebih.> str(f)
Factor w/ 4 levels "A","B","C","D": 2 1 3 2 1 4 1 4
> attributes(f)
$levels
[1] "A" "B" "C" "D"
$class
[1] "factor"
Untuk kembali ke nilai-nilai asli kita harus mengetahui nilai dari tingkat yang digunakan dalam menciptakan faktor. Dalam hal ini c(10, 20, 30, 40)
. Jika kita tahu tingkat asli (dalam urutan yang benar), kita dapat kembali ke nilai asli.
> orig_levels <- c(10, 20, 30, 40)
> x1 <- orig_levels[f]
> all.equal(x, x1)
[1] TRUE
Dan ini akan bekerja hanya dalam kasus ketika label yang telah didefinisikan untuk semua nilai yang mungkin dalam data asli.
Jadi jika anda akan memerlukan nilai-nilai asli, anda harus menjaga mereka. Jika tidak ada kesempatan yang tinggi itu tidak akan mungkin untuk kembali kepada mereka hanya dari satu faktor.
Anda dapat menggunakan hablar::mengkonversi
jika anda memiliki data frame. Sintaks adalah mudah:
Contoh df
library(hablar)
library(dplyr)
df <- dplyr::tibble(a = as.factor(c("7", "3")),
b = as.factor(c("1.5", "6.3")))
Solusi
df %>%
convert(num(a, b))
memberikan anda:
# A tibble: 2 x 2
a b
<dbl> <dbl>
1 7. 1.50
2 3. 6.30
Atau jika anda ingin satu kolom untuk menjadi integer dan satu numerik:
df %>%
convert(int(a),
num(b))
hasil:
# A tibble: 2 x 2
a b
<int> <dbl>
1 7 1.50
2 3 6.30