Saya memiliki data dari survei online di mana responden melewati putaran pertanyaan 1-3 kali. Perangkat lunak survei (Qualtrics) mencatat data ini dalam beberapa kolom-yaitu, Q3.2 dalam survei akan memiliki kolom Q3.2.1.
, Q3.2.2.
dan Q3.2.3.
:
df <- data.frame(
id = 1:10,
time = as.Date('2009-01-01') + 0:9,
Q3.2.1. = rnorm(10, 0, 1),
Q3.2.2. = rnorm(10, 0, 1),
Q3.2.3. = rnorm(10, 0, 1),
Q3.3.1. = rnorm(10, 0, 1),
Q3.3.2. = rnorm(10, 0, 1),
Q3.3.3. = rnorm(10, 0, 1)
)
# Sample data
id time Q3.2.1. Q3.2.2. Q3.2.3. Q3.3.1. Q3.3.2. Q3.3.3.
1 1 2009-01-01 -0.2059165 -0.29177677 -0.7107192 1.52718069 -0.4484351 -1.21550600
2 2 2009-01-02 -0.1981136 -1.19813815 1.1750200 -0.40380049 -1.8376094 1.03588482
3 3 2009-01-03 0.3514795 -0.27425539 1.1171712 -1.02641801 -2.0646661 -0.35353058
...
Saya ingin menggabungkan semua kolom QN.N * menjadi kolom QN.N individual yang rapi, yang pada akhirnya berakhir dengan sesuatu seperti ini:
id time loop_number Q3.2 Q3.3
1 1 2009-01-01 1 -0.20591649 1.52718069
2 2 2009-01-02 1 -0.19811357 -0.40380049
3 3 2009-01-03 1 0.35147949 -1.02641801
...
11 1 2009-01-01 2 -0.29177677 -0.4484351
12 2 2009-01-02 2 -1.19813815 -1.8376094
13 3 2009-01-03 2 -0.27425539 -2.0646661
...
21 1 2009-01-01 3 -0.71071921 -1.21550600
22 2 2009-01-02 3 1.17501999 1.03588482
23 3 2009-01-03 3 1.11717121 -0.35353058
...
The tidyr
perpustakaan memiliki gather()
fungsi, yang bekerja bagus untuk menggabungkan satu set kolom:
library(dplyr)
library(tidyr)
library(stringr)
df %>% gather(loop_number, Q3.2, starts_with("Q3.2")) %>%
mutate(loop_number = str_sub(loop_number,-2,-2)) %>%
select(id, time, loop_number, Q3.2)
id time loop_number Q3.2
1 1 2009-01-01 1 -0.20591649
2 2 2009-01-02 1 -0.19811357
3 3 2009-01-03 1 0.35147949
...
29 9 2009-01-09 3 -0.58581232
30 10 2009-01-10 3 -2.33393981
Bingkai data yang dihasilkan memiliki 30 baris, seperti yang diharapkan (10 individu, masing-masing 3 loop). Namun, mengumpulkan kumpulan kolom kedua tidak berfungsi dengan benar — ini berhasil membuat dua kolom gabungan Q3.2
dan Q3.3
, tetapi berakhir dengan 90 baris, bukan 30 (semua kombinasi 10 individu, 3 loop Q3.2, dan 3 loop Q3 .3; kombinasi akan meningkat secara substansial untuk setiap kelompok kolom dalam data aktual):
df %>% gather(loop_number, Q3.2, starts_with("Q3.2")) %>%
gather(loop_number, Q3.3, starts_with("Q3.3")) %>%
mutate(loop_number = str_sub(loop_number,-2,-2))
id time loop_number Q3.2 Q3.3
1 1 2009-01-01 1 -0.20591649 1.52718069
2 2 2009-01-02 1 -0.19811357 -0.40380049
3 3 2009-01-03 1 0.35147949 -1.02641801
...
89 9 2009-01-09 3 -0.58581232 -0.13187024
90 10 2009-01-10 3 -2.33393981 -0.48502131
Adakah cara untuk menggunakan beberapa panggilan untuk gather()
seperti ini, menggabungkan subkumpulan kecil kolom seperti ini sambil mempertahankan jumlah baris yang benar?
df %>% gather(loop_number, Q3.2, starts_with("Q3."))
seperate()
untuk membagi nilai Q3.3 (dan seterusnya) ke dalam kolom mereka sendiri. Tapi itu masih tampak seperti solusi yang tidak benar-benar bundar…spread
saya sedang mengerjakan solusi sekarang: pdf %>% gather(question_number, Q3.2, starts_with("Q3.")) %>% mutate(loop_number = str_sub(question_number,-2,-2), question_number = str_sub(question_number,1,4)) %>% select(id, time, loop_number, question_number, Q3.2) %>% spread(key = question_number, value = Q3.2)
spread()
. Meskipun beberapa panggilan tampaknya tak terhindarkan, baik itu sekumpulan panggilangenerate()
yang berhasil atau bertingkatspread()
...Jawaban:
Pendekatan ini tampaknya cukup alami bagi saya:
Pertama-tama kumpulkan semua kolom pertanyaan, gunakan
extract()
untuk memisahkan menjadiquestion
danloop_number
, kemudianspread()
pertanyaan kembali ke kolom.sumber
Ini bisa dilakukan dengan menggunakan
reshape
. Itu mungkin sajadplyr
.Atau menggunakan
dplyr
Memperbarui
Dengan
tidyr_0.8.3.9000
, kita bisa menggunakanpivot_longer
untuk membentuk kembali beberapa kolom. (Menggunakan nama kolom yang diubah darigsub
atas)CATATAN: Nilainya berbeda karena tidak ada benih yang ditetapkan dalam membuat set data masukan
sumber
mutate(loop_number = as.numeric(L2))
sebelum menjatuhkanL2
, dan itu sempurna.reshape
metode untuk kode ringkasnya, meskipundplyr
mungkin lebih cepat untuk kumpulan data besar.reshape()
fungsinya, lihat solusi saya untuk apa yang menurut saya implementasi tidyr yang cukup bersih.Dengan pembaruan terkini ke
melt.data.table
, kami sekarang dapat mencairkan banyak kolom. Dengan itu, kita bisa melakukan:Anda bisa mendapatkan versi pengembangan dari sini .
sumber
Ini sama sekali tidak terkait dengan "tidyr" dan "dplyr", tetapi berikut adalah opsi lain untuk dipertimbangkan:
merged.stack
dari paket "splitstackshape" saya , V1.4.0 dan yang lebih baru.sumber
Jika Anda seperti saya, dan tidak dapat mengetahui cara menggunakan "ekspresi reguler dengan menangkap grup" untuk
extract
, kode berikut mereplikasiextract(...)
baris dalam jawaban Hadley:Masalahnya di sini adalah bahwa pengumpulan awal membentuk kolom kunci yang sebenarnya merupakan kombinasi dari dua kunci. Saya memilih untuk menggunakan
mutate
solusi asli saya di komentar untuk membagi kolom ini menjadi dua kolom dengan info yang setara,loop_number
kolom danquestion_number
kolom.spread
kemudian dapat digunakan untuk mengubah data bentuk panjang, yang merupakan pasangan nilai kunci(question_number, value)
menjadi data bentuk lebar.sumber