Dalam kerangka data besar ("myfile") dengan empat kolom saya harus menambahkan kolom kelima dengan nilai bersyarat berdasarkan empat kolom pertama.
Lebih suka jawaban dengan dplyr
dan mutate
, terutama karena kecepatannya dalam kumpulan data besar.
Dataframe saya terlihat seperti ini:
V1 V2 V3 V4
1 1 2 3 5
2 2 4 4 1
3 1 4 1 1
4 4 5 1 3
5 5 5 5 4
...
Nilai kolom kelima (V5) didasarkan pada beberapa aturan bersyarat:
if (V1==1 & V2!=4) {
V5 <- 1
} else if (V2==4 & V3!=1) {
V5 <- 2
} else {
V5 <- 0
}
Sekarang saya ingin menggunakan mutate
fungsi untuk menggunakan aturan ini di semua baris (untuk menghindari loop lambat). Sesuatu seperti ini (dan ya, saya tahu itu tidak berfungsi seperti ini!):
myfile <- mutate(myfile, if (V1==1 & V2!=4){V5 = 1}
else if (V2==4 & V3!=1){V5 = 2}
else {V5 = 0})
Hasilnya akan seperti ini:
V1 V2 V3 V4 V5
1 1 2 3 5 1
2 2 4 4 1 2
3 1 4 1 1 0
4 4 5 1 3 0
5 5 5 5 4 0
Bagaimana melakukan ini dplyr
?
NA
, (NaN, +Inf, -Inf
)?dplyr
, maka saya akan lebih baik menggunakandata.table
.Jawaban:
Coba ini:
myfile %>% mutate(V5 = (V1 == 1 & V2 != 4) + 2 * (V2 == 4 & V3 != 1))
memberi:
V1 V2 V3 V4 V5 1 1 2 3 5 1 2 2 4 4 1 2 3 1 4 1 1 0 4 4 5 1 3 0 5 5 5 5 4 0
atau ini:
myfile %>% mutate(V5 = ifelse(V1 == 1 & V2 != 4, 1, ifelse(V2 == 4 & V3 != 1, 2, 0)))
memberi:
V1 V2 V3 V4 V5 1 1 2 3 5 1 2 2 4 4 1 2 3 1 4 1 1 0 4 4 5 1 3 0 5 5 5 5 4 0
Catatan
Sarankan Anda mendapatkan nama yang lebih baik untuk bingkai data Anda. myfile membuatnya tampak seolah-olah menyimpan nama file.
Di atas digunakan masukan ini:
myfile <- structure(list(V1 = c(1L, 2L, 1L, 4L, 5L), V2 = c(2L, 4L, 4L, 5L, 5L), V3 = c(3L, 4L, 1L, 1L, 5L), V4 = c(5L, 1L, 1L, 3L, 4L )), .Names = c("V1", "V2", "V3", "V4"), class = "data.frame", row.names = c("1", "2", "3", "4", "5"))
Perbarui 1 Sejak awalnya diposting dplyr telah berubah
%.%
menjadi%>%
jawaban sehingga telah diubah sesuai.Perbarui 2 dplyr sekarang
case_when
yang memberikan solusi lain:myfile %>% mutate(V5 = case_when(V1 == 1 & V2 != 4 ~ 1, V2 == 4 & V3 != 1 ~ 2, TRUE ~ 0))
sumber
ifelse
pernyataan:myfile %>% mutate(V5 = ifelse(V1 == 1 & V2 != 4, 1, 0), V5 = ifelse(V2 == 4 & V3 != 1, 2, V5))
Dengan
dplyr 0.7.2
, Anda dapat menggunakan fungsi yang sangat bergunacase_when
:x=read.table( text="V1 V2 V3 V4 1 1 2 3 5 2 2 4 4 1 3 1 4 1 1 4 4 5 1 3 5 5 5 5 4") x$V5 = case_when(x$V1==1 & x$V2!=4 ~ 1, x$V2==4 & x$V3!=1 ~ 2, TRUE ~ 0)
Dinyatakan dengan
dplyr::mutate
, itu memberi:x = x %>% mutate( V5 = case_when( V1==1 & V2!=4 ~ 1, V2==4 & V3!=1 ~ 2, TRUE ~ 0 ) )
Harap dicatat bahwa
NA
tidak diperlakukan secara khusus, karena dapat menyesatkan. Fungsi akan kembaliNA
hanya jika tidak ada kondisi yang cocok. Jika Anda meletakkan baris denganTRUE ~ ...
, seperti yang saya lakukan dalam contoh saya, nilai kembaliannya tidak akan pernahNA
.Oleh karena itu, Anda harus secara ekspresif memberi tahu
case_when
untuk meletakkannyaNA
dengan menambahkan pernyataan sukais.na(x$V1) | is.na(x$V3) ~ NA_integer_
. Petunjuk:dplyr::coalesce()
terkadang fungsi ini bisa sangat berguna di sini!Selain itu, perlu diketahui bahwa
NA
saja akan biasanya tidak bekerja, Anda harus meletakkan khususNA
nilai-nilai:NA_integer_
,NA_character_
atauNA_real_
.sumber
Sepertinya
derivedFactor
darimosaic
paket dirancang untuk ini. Dalam contoh ini, akan terlihat seperti ini:library(mosaic) myfile <- mutate(myfile, V5 = derivedFactor( "1" = (V1==1 & V2!=4), "2" = (V2==4 & V3!=1), .method = "first", .default = 0 ))
(Jika Anda ingin hasilnya berupa numerik, bukan faktor, bungkus
derivedFactor
denganas.numeric
.)Perhatikan bahwa
.default
opsi tersebut digabungkan dengan.method = "first"
kumpulan kondisi "lain" - pendekatan ini dijelaskan dalam file bantuan untukderivedFactor
.sumber
.asFactor = F
opsi atau dengan menggunakan fungsi (serupa)derivedVariable
dalam paket yang sama.recode
dari dplyr 0.5 akan melakukan ini. Saya belum menyelidikinya. Lihat blog.rstudio.org/2016/06/27/dplyr-0-5-0mosaic::derivedFactor
keluarga sangat lambat. Jika Anda mengetahui alasannya, harap jawab pertanyaan SO saya tentang hal itu: stackoverflow.com/questions/33787691/… . Saya senang melihat dari komentar Anda yang lain yangdplyr::case_when
lebih cepat - saya harus beralih ke itu.