logo

줄리아에서 빈도수 계산하는 법 📂줄리아

줄리아에서 빈도수 계산하는 법

개요 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