줄리아에서 빈도수 계산하는 법
개요 1
FreqTables.jl
패키지의 freqtable()
함수를 사용하면 된다. R에서의 freq()
함수와 유사한 기능을 한다.
코드
배열
julia> compartment = rand(['S','I','R'], 1000);
julia> freqtable(compartment)
3-element Named Vector{Int64}
Dim1 │
──────┼────
'I' │ 316
'R' │ 342
'S' │ 342
위와 같이 그냥 배열을 넣으면 각 계급별로 카운트 해준다.
데이터프레임
freqtable()
는 특히 데이터프레임에 유용하다. R에서의 질적변수를 포함한 회귀분석 예제와 마찬가지로 내장데이터 ToothGrowth
를 불러와보자.
julia> ToothGrowth = dataset("datasets", "ToothGrowth")
60×3 DataFrame
Row │ Len Supp Dose
│ Float64 Cat… Float64
─────┼────────────────────────
1 │ 4.2 VC 0.5
2 │ 11.5 VC 0.5
3 │ 7.3 VC 0.5
4 │ 5.8 VC 0.5
⋮ │ ⋮ ⋮ ⋮
58 │ 27.3 OJ 2.0
59 │ 29.4 OJ 2.0
60 │ 23.0 OJ 2.0
53 rows omitted
julia> freqtable(ToothGrowth, :Len)
43-element Named Vector{Int64}
Len │
─────┼──
4.2 │ 1
5.2 │ 1
5.8 │ 1
6.4 │ 1
⋮ ⋮
29.5 │ 1
30.9 │ 1
32.5 │ 1
33.9 │ 1
julia> freqtable(ToothGrowth, :Supp)
2-element Named Vector{Int64}
Supp │
──────┼───
"OJ" │ 30
"VC" │ 30
julia> freqtable(ToothGrowth, :Dose)
3-element Named Vector{Int64}
Dose │
──────┼───
0.5 │ 20
1.0 │ 20
2.0 │ 20
ToothGrowth
는 기니피그에게 비타민 C 혹은 오렌지 주스 :Supp
를 다른 양 :Dose
로 먹이고 치아의 길이 :Len
를 기록한 데이터다. 각 칼럼별로 빈도를 계산해보면 위와 같이 깔끔하게 정리해준다. 여기서 데이터가 반드시 범주형 데이터일 필요는 없음을 확인할 수 있다.
julia> freqtable(ToothGrowth, :Supp, :Dose)
2×3 Named Matrix{Int64}
Supp ╲ Dose │ 0.5 1.0 2.0
────────────┼──────────────
"OJ" │ 10 10 10
"VC" │ 10 10 10
물론 이러한 테이블은 범주형 데이터를 다룰 때 가장 효과적이다. :Supp
, :Dose
에 대해 빈도수를 계산해보면 알아서 2차원으로 카테고리를 나누어 빈도수를 계산해주었다.
julia> freqtable(ToothGrowth, :Len, :Dose, :Supp)
43×3×2 Named Array{Int64, 3}
[:, :, Supp="OJ"] =
Len ╲ Dose │ 0.5 1.0 2.0
───────────┼──────────────
4.2 │ 0 0 0
⋮ ⋮ ⋮ ⋮
33.9 │ 0 0 0
[:, :, Supp="VC"] =
Len ╲ Dose │ 0.5 1.0 2.0
───────────┼──────────────
4.2 │ 1 0 0
⋮ ⋮ ⋮ ⋮
33.9 │ 0 0 1
3개 이상의 칼럼에 대한 계산은 그냥 2차원 테이블을 계급의 수만큼 리턴한다. 이쯤되면 데이터를 탐색하거나 요약하는 의미는 거의 없다.
성능 비교
julia> @time for t in 1:10^4
freqtable(compartment)
end
@time for t in 1:10^4
count(compartment .== 'S')
count(compartment .== 'I')
count(compartment .== 'R')
end
0.068229 seconds (340.00 k allocations: 27.466 MiB)
0.059198 seconds (180.00 k allocations: 134.125 MiB, 36.71% gc time)
테이블을 떠나서 빈도수를 측정하는 것 자체가 유용하다는 생각이 든다. 이에 직접 카운트하는 것과 freqtable()
을 통해 한번에 빈도수를 계산하는 속도를 여러가지로 측정해봤는데, 어느 한 쪽이 반드시 빠르거나 하지는 않았다. 데이터의 수나 계급의 수에 따라서 엎치락뒤치락 하는데, 전반적으로 freqtable()
가 느린 편이었다. 그렇다고 엄청나게 밀리지도 않으니, 속도를 떠나 잘 고민해서 쓸 땐 쓰자.
전체코드
using FreqTables
compartment = rand(['S','I','R'], 1000);
freqtable(compartment)
using RDatasets
ToothGrowth = dataset("datasets", "ToothGrowth")
freqtable(ToothGrowth, :Len)
freqtable(ToothGrowth, :Supp)
freqtable(ToothGrowth, :Dose)
freqtable(ToothGrowth, :Supp, :Dose)
freqtable(ToothGrowth, :Len, :Dose, :Supp)
@time for t in 1:10^4
freqtable(compartment)
end
@time for t in 1:10^4
count(compartment .== 'S')
count(compartment .== 'I')
count(compartment .== 'R')
end
환경
- OS: Windows
- julia: v1.6.3
- FreqTables v0.4.5