Pertanyaan saya melibatkan penjumlahan nilai di beberapa kolom dari bingkai data dan membuat kolom baru yang sesuai dengan penjumlahan ini menggunakan dplyr
. Entri data di kolom adalah biner (0,1). Saya sedang memikirkan analog bijak darisummarise_each
atau mutate_each
fungsi dplyr
. Di bawah ini adalah contoh minimal dari bingkai data:
library(dplyr)
df=data.frame(
x1=c(1,0,0,NA,0,1,1,NA,0,1),
x2=c(1,1,NA,1,1,0,NA,NA,0,1),
x3=c(0,1,0,1,1,0,NA,NA,0,1),
x4=c(1,0,NA,1,0,0,NA,0,0,1),
x5=c(1,1,NA,1,1,1,NA,1,0,1))
> df
x1 x2 x3 x4 x5
1 1 1 0 1 1
2 0 1 1 0 1
3 0 NA 0 NA NA
4 NA 1 1 1 1
5 0 1 1 0 1
6 1 0 0 0 1
7 1 NA NA NA NA
8 NA NA NA 0 1
9 0 0 0 0 0
10 1 1 1 1 1
Saya bisa menggunakan sesuatu seperti:
df <- df %>% mutate(sumrow= x1 + x2 + x3 + x4 + x5)
tetapi ini akan melibatkan penulisan nama masing-masing kolom. Saya memiliki 50 kolom. Selain itu, nama kolom berubah pada iterasi yang berbeda dari loop di mana saya ingin menerapkan operasi ini, jadi saya ingin mencoba menghindari keharusan memberikan nama kolom apa pun.
Bagaimana saya bisa melakukannya dengan paling efisien? Bantuan apa pun akan sangat dihargai.
dplyr
? Mengapa tidak hanya yang sederhanadf$sumrow <- rowSums(df, na.rm = TRUE)
dari basis R? Ataudf$sumrow <- Reduce(`+`, df)
jika Anda ingin meniru persis hal yang Anda lakukan dengandplyr
.dplyr
too as indf %>% mutate(sumrow = Reduce(`+`, .))
ataudf %>% mutate(sumrow = rowSums(.))
dplyr
versi terbaru dan itu akan berfungsi.Jawaban:
Bagaimana tentang
jumlahkan setiap kolom
df %>% replace(is.na(.), 0) %>% summarise_all(funs(sum))
jumlahkan setiap baris
df %>% replace(is.na(.), 0) %>% mutate(sum = rowSums(.[1:5]))
sumber
summarise_each
menjumlahkan di sepanjang setiap kolom sementara yang diperlukan adalah jumlah di setiap baris(.[1:5])
bagian tersebut, tetapi sayangnya saya tidak terbiasa dengan sintaksnya atau saya tidak tahu cara mencari bantuan untuk itu. Sudah mencobamutate(sum = rowSums(is.numeric(.)))
tapi tidak berhasil.df %>% replace(is.na(.), 0) %>% select_if(is.numeric) %>% summarise_each(funs(sum))
?summarise_all
alih-alihsummarise_each
seperti yang sudah tidak digunakan lagi.mutate(sum = rowSums(.[,-1]))
mungkin berguna jika Anda tidak tahu berapa banyak kolom yang perlu Anda tangani.Jika Anda ingin menjumlahkan kolom tertentu saja, saya akan menggunakan sesuatu seperti ini:
library(dplyr) df=data.frame( x1=c(1,0,0,NA,0,1,1,NA,0,1), x2=c(1,1,NA,1,1,0,NA,NA,0,1), x3=c(0,1,0,1,1,0,NA,NA,0,1), x4=c(1,0,NA,1,0,0,NA,0,0,1), x5=c(1,1,NA,1,1,1,NA,1,0,1)) df %>% select(x3:x5) %>% rowSums(na.rm=TRUE) -> df$x3x5.total head(df)
Dengan cara ini Anda dapat menggunakan
dplyr::select
sintaks.sumber
Saya akan menggunakan pencocokan ekspresi reguler untuk menjumlahkan variabel dengan nama pola tertentu. Sebagai contoh:
df <- df %>% mutate(sum1 = rowSums(.[grep("x[3-5]", names(.))], na.rm = TRUE), sum_all = rowSums(.[grep("x", names(.))], na.rm = TRUE))
Dengan cara ini Anda dapat membuat lebih dari satu variabel sebagai jumlah grup variabel tertentu dari bingkai data Anda.
sumber
-
tanda:rowSums(.[-grep("x[3-5]", names(.))], na.rm = TRUE)
Saya sering mengalami masalah ini, dan cara termudah untuk melakukannya adalah dengan menggunakan
apply()
fungsi di dalammutate
perintah.library(tidyverse) df=data.frame( x1=c(1,0,0,NA,0,1,1,NA,0,1), x2=c(1,1,NA,1,1,0,NA,NA,0,1), x3=c(0,1,0,1,1,0,NA,NA,0,1), x4=c(1,0,NA,1,0,0,NA,0,0,1), x5=c(1,1,NA,1,1,1,NA,1,0,1)) df %>% mutate(sum = select(., x1:x5) %>% apply(1, sum, na.rm=TRUE))
Di sini Anda dapat menggunakan apa pun yang Anda inginkan untuk memilih kolom menggunakan
dplyr
trik standar (mis.starts_with()
Ataucontains()
). Dengan melakukan semua pekerjaan dalam satumutate
perintah, tindakan ini dapat terjadi di mana saja dalamdplyr
aliran langkah pemrosesan. Terakhir, dengan menggunakan fileapply()
fungsi tersebut, Anda memiliki fleksibilitas untuk menggunakan ringkasan apa pun yang Anda butuhkan, termasuk fungsi peringkasan yang dibuat untuk tujuan Anda sendiri.Alternatifnya, jika gagasan menggunakan fungsi non-tidyverse tidak menarik, maka Anda bisa mengumpulkan kolom, meringkasnya dan akhirnya menggabungkan hasilnya kembali ke bingkai data asli.
df <- df %>% mutate( id = 1:n() ) # Need some ID column for this to work df <- df %>% group_by(id) %>% gather('Key', 'value', starts_with('x')) %>% summarise( Key.Sum = sum(value) ) %>% left_join( df, . )
Di sini saya menggunakan
starts_with()
fungsi untuk memilih kolom dan menghitung jumlahnya dan Anda dapat melakukan apa pun yang Anda inginkan denganNA
nilai. Kelemahan dari pendekatan ini adalah meskipun cukup fleksibel, ia tidak benar-benar cocok dengandplyr
aliran langkah pembersihan data.sumber
apply
saat ini adalah aparowSums
yang dirancang untuk itu.rowSums
bekerja sangat baik jugarowMeans
, tetapi saya selalu merasa agak aneh bertanya-tanya tentang "Bagaimana jika hal yang perlu saya hitung bukanlah penjumlahan atau mean?" Namun, 99% dari waktu saya harus melakukan sesuatu seperti ini, entah itu penjumlahan atau mean, jadi mungkin sedikit ekstra fleksibilitas dalam menggunakanapply
fungsi umum tidak diberikan.Menggunakan
reduce()
frompurrr
sedikit lebih cepat daripadarowSums
dan pasti lebih cepat daripadaapply
, karena Anda menghindari iterasi pada semua baris dan hanya memanfaatkan operasi vektorisasi:library(purrr) library(dplyr) iris %>% mutate(Petal = reduce(select(., starts_with("Petal")), `+`))
Lihat ini untuk pengaturan waktu
sumber
na.rm = TRUE
rowSums(select(., matches("myregex")) , na.rm = TRUE))
karena itulah yang saya butuhkan dalam hal mengabaikan NAs. Jadi jika angkanya adalahsum(NA, 5)
hasilnya 5. Tetapi Anda mengatakan mengurangi lebih baik daripadarowSums
jadi saya bertanya-tanya apakah ada cara untuk menggunakannya dalam situasi ini?rowSums
versinya mungkin yang terbaik. Kerugian utama adalah bahwa hanyarowSums
danrowMeans
tersedia (itu sedikit lebih lambat daripada mengurangi, tetapi tidak banyak). Jika Anda perlu melakukan operasi lain (bukan penjumlahan) makareduce
versi mungkin satu-satunya pilihan. Hindari penggunaanapply
dalam kasus ini.Dalam versi yang lebih baru
dplyr
Anda dapat menggunakanrowwise()
bersama denganc_across
untuk melakukan agregasi berdasarkan baris untuk fungsi yang tidak memiliki varian berdasarkan baris tertentu, tetapi jika varian bijak baris ada, seharusnya lebih cepat.Karena
rowwise()
ini hanya bentuk pengelompokan khusus dan mengubah cara kerja kata kerja, Anda mungkin ingin menyalurkannyaungroup()
setelah melakukan operasi baris-bijaksana Anda.Untuk memilih berbagai baris:
df %>% dplyr::rowwise() %>% dplyr::mutate(sumrange = sum(dplyr::c_across(x1:x5), na.rm = T)) # %>% dplyr::ungroup() # you'll likely want to ungroup after using rowwise()
Untuk memilih baris berdasarkan jenis:
df %>% dplyr::rowwise() %>% dplyr::mutate(sumnumeric = sum(c_across(where(is.numeric)), na.rm = T)) # %>% dplyr::ungroup() # you'll likely want to ungroup after using rowwise()
Dalam kasus khusus Anda, ada varian berdasarkan baris sehingga Anda dapat melakukan hal berikut (perhatikan penggunaan
across
sebagai gantinya):df %>% dplyr::mutate(sumrow = rowSums(dplyr::across(x1:x5), na.rm = T)) # %>% dplyr::ungroup() # you'll likely want to ungroup after using rowwise()
Untuk informasi lebih lanjut, lihat halaman di rowwise .
sumber