Updated: 2021-09-17
Hari ni bersempena Hari kemerdekaan Malaysia ada masa untuk ulang kaji pakej
data.table. Hari ni ialah mengenai Special Symbol seperti .N, .I, .GRP, .BY
.
Penerangan ini diambil dari manual di data.table
tetapi diedit sedikit. Untuk
rujukan di sini.
Ini data yang dipakai untuk membuat contoh:
DT = data.table(x=rep(c("b","a","c"),each=3), v=c(1,1,1,2,2,1,1,2,2), y=c(1,6,3,7,8), a=1:9, b=9:1)
X = data.table(x=c("c","b"), v=8:7, foo=c(4,2))
.N
Penggunaan .N
selain dari untuk mendapatkan jumlah baris di dataset, .N
boleh juga
digunakan untuk melihat barisan terakhir di dataset. Untuk melihat barisan pertama
guna DT[1]
.
DT[.N] # last row, only special symbol allowed in 'i' - nesten som Total
DT[, .N] # total number of rows in DT
DT[, .N, by=x] # number of rows in each group
Mult
Contoh untuk penggunaan mult
(multiple rows) adalah seperti di bawah. Penggunaan
fungsi mult ialah untuk menetapkan kombinasi barisan yang ingin ditunjukkan samada
“all”, “first” atau “last”. Variable x
dan y
boleh disusun dengan menggunakan
setkey(DT, x, y)
. Sekiranya tidak disusun terlebih dahulu sebelum dipakai maka harus
menggunakan fungsi on
seperti contoh di bawah.
## contoh data
dt <- data.table(x = c(1, 1, 3, 1, 7),
y = c(1, 2, 3, 2, 6))
setkey(dt, x)
## dapatkan kombinasi yang unik
udt <- unique(dt)
## buat kolom dengan nilai 0
dt[, c("first", "last") := 0L][]
x y first last
1: 1 1 0 0
2: 1 2 0 0
3: 1 2 0 0
4: 3 3 0 0
5: 7 6 0 0
Menggunakan mult
untuk menetapkan kombinasi unik yang diingini. Pemakaian "first"
menunjukkan kombinasi pertama sahaja. Sekiranya kombinasi yang sama terdapat
dipelbagai baris, hanya barisan yang pertama dimana kombinasi tersebut ditemui akan
dipilih. Pemakaian "last"
memilih barisan terakhir dimana kombinasi yang diingini ditemui.
## Sekiranya kombinasi x,y yang pertama terdapat
## di data masukkan 1 di kolom "first"
dt[udt, first := 1L, on = c("x", "y"), mult = "first"][]
## Sekiranya kombinasi x,y yang terakhir terdapat
## di data masukkan nilai 1 di kolom "last"
dt[udt, last := 1L, on = c("x", "y"), mult = "last"][]
x y first last
1: 1 1 1 1
2: 1 2 1 0
3: 3 3 1 1
4: 1 2 0 1
5: 7 6 1 1
Contoh di bawah menunjukkan cara sekiranya hanya ingin mendapatkan index kombinasi yang diingini sahaja.
## Untuk lihat indeks bagi kombinasi yang unik sahaja
dt[unique(dt), on = c("x", "y"), mult = "first", which = TRUE]
[1] 1 2 3 5
Contoh lain menggunakan mult
. Seperti kajian isi rumah (household) dimana “id”
mewakili rumah. Semua ahli keluarga mempunyai id-rumah sama. Sekiranya ingin
mencari ahli termuda atau tertua fungsi mult
dapat memudahkan proses.
set.seed(1234)
dt <- data.table(id = sample(1:4, 10, TRUE),
umur = sample(20:35, 10, TRUE),
jentina = sample(1:2, 10, TRUE),
kode = sample(1:5, 2, TRUE))
## Susun umur mengikut id
setkey(dt, id, umur)
## first ialah id yang sama ahli yang paling muda
dt[unique(dt), muda := 1L, on = list(id), mult = "first"][]
## Pilih yang terakhir dari id yang sama - cth utk pilih ahli tertua
## sekiranya tidak pakai list di 'on = list(nama-var)' boleh pakai "nama-var".
dt[unique(dt), tua := as.integer(1L), on = "id", mult = "last", by = .(umur)][]
## pilih nilai pertama untuk setiap kombinasi unik antara 'id' dan 'kode'
dt[unique(dt[, c("id", "kode")]), KodePertama := 1L, on = list(id, kode), mult = "first"][]
## pilih nilai terakhir untuk setiap kombinasi unik antara 'id' dan 'kode'
dt[unique(dt[, c("id", "kode")]), KodeAkhir := 1L, on = c("id", "kode"), mult = "last"][]
Hasilnya dari contoh pemilihan ahli yang paling muda dan tua dari data di atas
menggunakan "first"
dan "last"
. Pemakaian unique(dt)
berasaskan dari penetapan yang dibuat
di fungsi setkey
dimana data disusun mengikut id
kemudian umur
terlebih dahulu.
Sekiranya pemilihan kombinasi unik berasaskan kolom lain, selain dari id
dan umur
yang telah ditetapkan, pemilihan kolom unik boleh dibuat secara fungsi asas
menggunakan unique(dt[, c("kol1", "kol2")])
. Penggunaan on
boleh memakai cara
list
atau concatenate
.
id umur jentina kode muda tua KodePertama KodeAkhir
1: 1 24 2 3 1 NA 1 NA
2: 1 24 2 2 NA NA 1 1
3: 1 31 1 3 NA 1 NA 1
4: 3 22 2 3 1 NA 1 NA
5: 3 23 1 2 NA NA 1 NA
6: 3 24 1 3 NA NA NA 1
7: 3 28 1 2 NA NA NA NA
8: 3 33 2 2 NA NA NA NA
9: 3 34 1 2 NA 1 NA 1
10: 4 24 1 3 1 1 1 1
.SD dan .SDcols
Penggunaan .SD
juga boleh berasaskan indeks barisan. Contoh untuk menggunakan .SDcols
seperti di bawah termasuk menggunakan fungsi lapply
. Tetapi penggunaan ".SD"
adalah
lebih lambat berbanding menggunakan fungsi "on"
seperti di atas.
# pilih kolom 'x' dan 'y'
DT[, .SD, .SDcols = x:y]
# baris pertama di semua kolom
DT[, .SD[1]]
# baris pertama di 'y' dan 'v' untuk setiap kumpulan di 'x'
DT[, .SD[1], by = x]
# get rows *and* sum all col
DT[, c(.N, lapply(.SD, sum)), by = x]
# get rows *and* sum columns 'v' and 'y' by group
DT[, c(.N, lapply(.SD, sum)), by = x, .SDcol = c("v", "y")]
.I
Untuk dapatkan indeks barisan simbol .I
boleh dipakai. Hanya vektor untuk indeks
barisan yang akan diberikan dan tidak nilai di indeks tersebut. Fungsinya sama
seperti seq_len(nrow(x))
. Semasa penggumpulan dibuat, pada masa yang sama
penggumpulan dilakukan di dalam kumpulan yang ditetapkan. Sesuai digunakan untuk
membuat subset di j
seperti: DT[,.I[which.max(somecol)], by=grp]
. Penggunaannya
same seperti fungsi which
di base.
Buat identity
Cara lain boleh digunakan untuk membuat indentity atau ID. DT[, id := .I]
seperti menggunakan DT[, id := seq_len(.N)
Dapatkan barisan pertama
Pemakaian .I[1]
contohny digunakan untuk mendapatkan index dimana nilai pertama
bagi setiap kumpulan di x
. Untuk kumpulan b
di kolom x
, nilai pertama ialah di
barisan 1, nilai pertama bagi kumpulan a
di kolom x
ialah di barian ke 4 dan
nilai pertama kumpulan c
di barisan ke 7.
DT
x v y a b
1: b 1 1 1 9
2: b 1 6 2 8
3: b 1 3 3 7
4: a 2 7 4 6
5: a 2 8 5 5
6: a 1 1 6 4
7: c 1 6 7 3
8: c 2 3 8 2
9: c 2 7 9 1
DT[, .I[1], by = x] # first row number in DT corresponding to each group
x V1
1: b 1
2: a 4
3: c 7
DT[, .(index = .I[1]), by = x] # Namakan variable untuk index
x index
1: 1 1
2: 3 4
3: 7 5
Dapatkan barisan nilai maksium
Untuk dapatkan index bagi nilai maksimum mengikut kumpulan di kolom x
boleh dibuat
seperti cara di bawah.
DT[, .I[which.max(y)], by = x] # which row number with the max 'y' by 'x'
x V1
1: b 2
2: a 5
3: c 9
Buat subset
Untuk membuat subset data berdasarkan nilai atau kategori tertentu seperti setiap tahun.
## Dapatkan index barisan
DT[, .I[sample(age, 5)], by = year]
## Subset data dari index
DT[DT[, I[sample(age, 5)], by = year]$V1]
.GRP dan rleid
Untuk mengkaji menggikut kumpulan secara penyusunan.
DT[, grp := .GRP, by = x][] # add a group counter
x v y a b grp
1: b 1 1 1 9 1
2: b 1 6 2 8 1
3: b 1 3 3 7 1
4: a 2 7 4 6 2
5: a 2 8 5 5 2
6: a 1 1 6 4 2
7: c 1 6 7 3 3
8: c 2 3 8 2 3
9: c 2 7 9 1 3
DT[, .N, by = rleid(v)] # get count of consecutive runs of 'v'
rleid N
1: 1 3
2: 2 2
3: 3 2
4: 4 2
DT[, c(.(ym = max(y)), lapply(.SD, min)), by = rleid(v), .SDcols = v:b] # compute 'j' for each consecutive runs of 'v'
rleid ym v y a b
1: 1 6 1 1 1 7
2: 2 8 2 7 4 5
3: 3 6 1 1 6 3
4: 4 7 2 3 8 1
Untuk gabungkan dua dataset. Tapi cara ini masih tidak difahami :-(
X
x v foo
1: c 8 4
2: b 7 2
## need more info for this
X[, DT[.BY, y, on = "x"], by = x] # join within each group
x V1
1: c 6
2: c 3
3: c 7
4: b 1
5: b 6
6: b 3
Untuk tukar nilai bagi setiap barisan pertama di kumpulan yang sama. Ini biasanya dipakai contohnya bila membuat kajian keluarga dan ingin memberikan kod tertentu yang membezakan keluarga 1 dan 2 dsb.
Cara ini tidak hard code data. Kolom c
tidak dimasukkan ke data dan hanya
disimpan di memory sahaja. Untuk simpan harus assign to save object atau gunakan cara mult
.
## Recode to 99 for first row in each group by x
DT[, {vDT = copy(.SD) #kopi semua kolom
vDT[1, c := 99] #buat kolom C row pertama nilai 99
vDT},
by = x]
x v y a b grp c
1: b 1 1 1 9 1 99
2: b 1 6 2 8 1 NA
3: b 1 3 3 7 1 NA
4: a 2 7 4 6 2 99
5: a 2 8 5 5 2 NA
6: a 1 1 6 4 2 NA
7: c 1 6 7 3 3 99
8: c 2 3 8 2 3 NA
9: c 2 7 9 1 3 NA
DT[unique(x), d:=99, on = "x", mult = "first"][]
Contoh dari manual
Ini ialah contoh dan penerangan dari manual sekiranya penerangan diatas tidak difahami.
## Not run:
DT = data.table(x=rep(c("b","a","c"),each=3), v=c(1,1,1,2,2,1,1,2,2), y=c(1,3,6), a=1:9, b=9:1)
DT
X = data.table(x=c("c","b"), v=8:7, foo=c(4,2))
X
DT[.N] # last row, only special symbol allowed in 'i'
DT[, .N] # total number of rows in DT
DT[, .N, by=x] # number of rows in each group
DT[, .SD, .SDcols=x:y] # select columns 'x' and 'y'
DT[, .SD[1]] # first row of all columns
DT[, .SD[1], by=x] # first row of 'y' and 'v' for each group in 'x'
DT[, c(.N, lapply(.SD, sum)), by=x] # get rows *and* sum all columns by group
DT[, .I[1], by=x] # row number in DT corresponding to each group starting point
DT[, .N, by=rleid(v)] # get count of consecutive runs of 'v'
DT[, c(.(y=max(y)), lapply(.SD, min)),
by=rleid(v), .SDcols=v:b] # compute 'j' for each consecutive runs of 'v'
DT[, grp := .GRP, by=x] # add a group counter
X[, DT[.BY, y, on="x"], by=x] # join within each group
## End(Not run)