Saya menggunakan fungsi ifelse()
untuk memanipulasi vektor tanggal. Saya mengharapkan hasilnya dari kelas Date
, dan terkejut mendapatkan numeric
vektor sebagai gantinya. Berikut ini sebuah contoh:
dates <- as.Date(c('2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04', '2011-01-05'))
dates <- ifelse(dates == '2011-01-01', dates - 1, dates)
str(dates)
Ini terutama mengejutkan karena melakukan operasi di seluruh vektor mengembalikan suatu Date
objek.
dates <- as.Date(c('2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04','2011-01-05'))
dates <- dates - 1
str(dates)
Haruskah saya menggunakan beberapa fungsi lain untuk beroperasi pada Date
vektor? Jika demikian, apa fungsinya? Jika tidak, bagaimana cara memaksa ifelse
untuk mengembalikan vektor dengan tipe yang sama dengan input?
Halaman bantuan untuk ifelse
menunjukkan bahwa ini adalah fitur, bukan bug, tapi saya masih berjuang untuk menemukan penjelasan untuk apa yang saya temukan sebagai perilaku mengejutkan.
r
datetime
if-statement
Zach
sumber
sumber
if_else()
dalam paket dplyr yang bisa menggantikanifelse
sementara mempertahankan kelas objek Date yang benar - itu diposting di bawah ini sebagai jawaban baru-baru ini. Saya membawa perhatian ke sini karena ini memecahkan masalah ini dengan menyediakan fungsi yang diuji unit dan didokumentasikan dalam paket CRAN, tidak seperti banyak jawaban lain yang (pada komentar ini) berada di peringkat di depannya.Jawaban:
Anda dapat menggunakan
data.table::fifelse
(data.table >= 1.12.3
) ataudplyr::if_else
.data.table::fifelse
dplyr::if_else
Dari
dplyr 0.5.0
catatan rilis :sumber
true
danfalse
level.if_else
be NA? Saya sudah mencobaNA_
opsi logis dan tidak ada yang menempel dan saya tidak percaya adaNA_double_
NA
dias.Date
.NA_real_
, @roarkz. dan @ Henrik, komentar Anda di sini memecahkan masalah saya.Ini terkait dengan Nilai terdokumentasi dari
ifelse
:Dimasukkan ke implikasinya,
ifelse
membuat faktor kehilangan level mereka dan Tanggal kehilangan kelas mereka dan hanya mode mereka ("numerik") yang dipulihkan. Coba ini sebagai gantinya:Anda dapat membuat
safe.ifelse
:Catatan selanjutnya: Saya melihat Hadley telah membangun sebuah
if_else
kompleks magrittr / dplyr / tidyr dari paket-paket pembentuk data.sumber
safe.ifelse <- function(cond, yes, no) structure(ifelse(cond, yes, no), class = class(yes))
ifelse()
belum "aman" .Penjelasan DWin tepat. Saya mengutak-atik dan bertarung dengan ini untuk sementara waktu sebelum saya menyadari bahwa saya bisa memaksa kelas setelah pernyataan ifelse:
Pada awalnya ini terasa sedikit "retas" bagi saya. Tapi sekarang saya hanya menganggapnya sebagai harga kecil untuk membayar pengembalian kinerja yang saya dapatkan dari ifelse (). Plus itu masih jauh lebih ringkas daripada satu lingkaran.
sumber
for
pernyataan yang ditunjuk dengan nilai dari item dalamVECTOR
untukNAME
, tetapi tidak mereka kelas .Metode yang disarankan tidak bekerja dengan kolom faktor. Saya ingin menyarankan peningkatan ini:
Ngomong-ngomong: ifelse menyebalkan ... dengan kekuatan besar datang tanggung jawab besar, yaitu konversi tipe matriks 1x1 dan / atau numerik [ketika harus ditambahkan misalnya] tidak masalah bagi saya tetapi konversi tipe ini dalam ifelse jelas tidak diinginkan. Saya bertemu 'bug' yang sama dari ifelse beberapa kali sekarang dan itu terus mencuri waktu saya :-(
FW
sumber
yes
danno
dan Anda akan memeriksa dulu untuk melihat bahwa keduanya adalah faktor. Anda mungkin perlu mengkonversi ke karakter dan kemudian menyatukan kembali dengan tingkat-"serikat".Alasan mengapa ini tidak berhasil adalah karena, fungsi ifelse () mengubah nilai menjadi faktor. Solusi yang bagus adalah dengan mengubahnya menjadi karakter sebelum mengevaluasinya.
Ini tidak memerlukan perpustakaan apa pun selain dari basis R.
sumber
Jawaban yang diberikan oleh @ fabian-werner sangat bagus, tetapi objek dapat memiliki beberapa kelas, dan "faktor" mungkin belum tentu yang pertama dikembalikan oleh
class(yes)
, jadi saya sarankan modifikasi kecil ini untuk memeriksa semua atribut kelas:Saya juga telah mengajukan permintaan dengan tim Pengembangan R untuk menambahkan opsi yang didokumentasikan untuk memiliki basis :: ifelse () melestarikan atribut berdasarkan pilihan pengguna yang atributnya akan dipertahankan. Permintaannya ada di sini: https://bugs.r-project.org/bugzilla/show_bug.cgi?id=16609 - Sudah ditandai sebagai "WONTFIX" dengan alasan selalu seperti sekarang, tapi saya telah memberikan argumen tindak lanjut tentang mengapa penambahan sederhana mungkin menghemat banyak sakit kepala pengguna R. Mungkin "+1" Anda di utas bug itu akan mendorong tim R Core untuk melihat kembali.
EDIT: Berikut adalah versi yang lebih baik yang memungkinkan pengguna untuk menentukan atribut mana yang harus dipertahankan, baik perilaku "cond" (perilaku ifelse () default), "ya", perilaku sesuai kode di atas, atau "tidak", untuk kasus di mana atribut nilai "tidak" lebih baik:
sumber
inherits(y, "factor")
mungkin "lebih benar" dari"factor" %in% class.y
inherits
mungkin yang terbaik.