Flux in Julia/Learning Julia (Intro_to_Julia_DFs)
11. performance (한글)
딥스탯
2018. 10. 18. 14:18
Introduction to DataFrames¶
Bogumił Kamiński, Apr 21, 2018
출처¶
함께보기¶
- https://deepstat.tistory.com/69 (01. constructors)(in English)
- https://deepstat.tistory.com/70 (01. constructors)(한글)
- https://deepstat.tistory.com/71 (02. basicinfo)(in English)
- https://deepstat.tistory.com/72 (02. basicinfo)(한글)
- https://deepstat.tistory.com/73 (03. missingvalues)(in English)
- https://deepstat.tistory.com/74 (03. missingvalues)(한글)
- https://deepstat.tistory.com/75 (04. loadsave)(in English)
- https://deepstat.tistory.com/76 (04. loadsave)(한글)
- https://deepstat.tistory.com/77 (05. columns)(in English)
- https://deepstat.tistory.com/78 (05. columns)(한글)
- https://deepstat.tistory.com/79 (06. rows)(in English)
- https://deepstat.tistory.com/80 (06. rows)(한글)
- https://deepstat.tistory.com/81 (07. factors)(in English)
- https://deepstat.tistory.com/82 (07. factors)(한글)
- https://deepstat.tistory.com/83 (08. joins)(in English)
- https://deepstat.tistory.com/84 (08. joins)(한글)
- https://deepstat.tistory.com/85 (09. reshaping)(in English)
- https://deepstat.tistory.com/86 (09. reshaping)(한글)
- https://deepstat.tistory.com/87 (10. transforms)(in English)
- https://deepstat.tistory.com/88 (10. transforms)(한글)
- https://deepstat.tistory.com/89 (11. performance)(in English)
- https://deepstat.tistory.com/90 (11. performance)(한글)
In [1]:
using DataFrames
using BenchmarkTools
성능향상을 위한 팁¶
행 숫자로 불러내는 것이 행 이름을 사용하는 것보다 빠르다.¶
In [2]:
x = DataFrame(rand(5, 1000))
@btime x[500];
@btime x[:x500];
데이터프레임
을 다룰 때 장벽 함수(barrier function)이나 주석을 적는 것(typing annotation)이 좋다.¶
In [3]:
using Random
function f_bad() # this function will be slow
Random.seed!(1); x = DataFrame(rand(1000000,2))
y, z = x[1], x[2]
p = 0.0
for i in 1:nrow(x)
p += y[i]*z[i]
end
p
end
@btime f_bad();
In [4]:
@code_warntype f_bad() # 느린 이유는 Julia가 데이터프레임의 행 타입을 모르기 때문이다.
In [5]:
# 솔루션 1은 장벽 함수 (barrier functiion)을 쓰는 것이다. (거의 모든 코드안에서 쓸 수 있다.)
function f_inner(y,z)
p = 0.0
for i in 1:length(y)
p += y[i]*z[i]
end
p
end
function f_barrier() # 내부 함수(inner function)로 일을 보낸다.
Random.seed!(1); x = DataFrame(rand(1000000,2))
f_inner(x[1], x[2])
end
using LinearAlgebra
function f_inbuilt() # 혹은 가능하다면 내장 함수(inbuilt function)을 사용한다.
Random.seed!(1); x = DataFrame(rand(1000000,2))
x[1] ⋅ x[2] #\cdot<tab>
end
@btime f_barrier();
@btime f_inbuilt();
In [6]:
# 솔루션 2는 추출된 열에 타입을 제공하는 것이다.
# 이는 더 간단한 방법이지만 타입을 모르는 경우에는 사용할 수 없다.
function f_typed()
Random.seed!(1); x = DataFrame(rand(1000000,2))
y::Vector{Float64}, z::Vector{Float64} = x[1], x[2]
p = 0.0
for i in 1:nrow(x)
p += y[i]*z[i]
end
p
end
@btime f_typed();
지연된(delayed) 데이터프레임
생성 테크닉 사용하기.¶
In [7]:
function f1()
x = DataFrame(Float64, 10^4, 100) # 바로 데이터프레임 만들어서 사용하기
for c in 1:ncol(x)
d = x[c]
for r in 1:nrow(x)
d[r] = rand()
end
end
x
end
function f2()
x = Vector{Any}(undef, 100)
for c in 1:length(x)
d = Vector{Float64}(undef,10^4)
for r in 1:length(d)
d[r] = rand()
end
x[c] = d
end
DataFrame(x) # 전부 다 계산하고 난 다음에 데이터프레임 만들기
end
@btime f1();
@btime f2();
데이터프레임
에 in place로 행을 추가하는 것이 더 빠르다.¶
- 근데 크기(size)가 왜 변하는지 모르겠다. 원문에는 따로 설명이 없다.
In [8]:
x = DataFrame(rand(10^6, 5))
y = DataFrame(transpose(1.0:5.0))
z = [1.0:5.0;]
println("Size of original x = ",size(x))
@btime vcat($x, $y); # creates a new DataFrame - slow
println("Size of result after running vcat = ", size(vcat(x,y)))
@btime push!($x, $z); # add a single row in place - fast
println("Size of x after running push! = ", size(x))
println(" ")
x = DataFrame(rand(10^6, 5)) # reset to the same starting point
println("Size of original x = ", size(x))
@btime append!($x, $y); # in place - fastest
println("Size of x after running append! = ", size(x))
범주형(categorical)
타입이나 결측(missing)
타입을 허용하면 계산이 느려진다.¶
In [9]:
using StatsBase
function test(data) # uses countmap function to test performance
println(eltype(data))
x = rand(data, 10^6)
y = categorical(x)
println(" raw:")
@btime countmap($x)
println(" categorical:")
@btime countmap($y)
nothing
end
println("Using test(1:10)")
test(1:10)
println(" ")
println("Using test([randstring() for i in 1:10])")
test([randstring() for i in 1:10])
println(" ")
println("Using test(allowmissing(1:10))")
test(allowmissing(1:10))
println(" ")
println("Using test(allowmissing([randstring() for i in 1:10]))")
test(allowmissing([randstring() for i in 1:10]))