顯示具有 julia 標籤的文章。 顯示所有文章
顯示具有 julia 標籤的文章。 顯示所有文章

2019/6/16

julia Data Visulization


分成三個部分: Basic Plots, Vega, Gadfly,討論如何在 julia 進行 data visulization


Basic plots


使用 PyPlot,這是以 python matplotlib.pyplot module 提供的功能


使用前要先安裝 matplotlib


python -m pip install matplotlib

在 julia 安裝 PyPlot


 Pkg.add("PyPlot")

用以下指令在 julia 測試 PyPlot


using PyPlot
x = 1:100
y = rand(100)
p = PyPlot.plot(x,y)
xlabel("x")
ylabel("y")
title("basic plot")
grid("true")

會得到這樣的圖形結果



另一個例子


using PyPlot

x = range(0, stop=4pi, length=1000)
y = cos.(pi .+ sin.(x))

xlabel("x-axis")
ylabel("y-axis")
title("using sin and cos functions")

plot(x, y, color="red")


XKCD 是一種 casual-style, handwritten graph mode


using PyPlot

x = [1:1:10;]
y = ones(10)

for i = 1:1:10
    y[i] = pi + i*i
end

xkcd()
xlabel("x-axis")
ylabel("y-axis")
title("XKCD")
plot(x,y)


bar chart


using PyPlot

x = [10,20,30,40,50]
y = [2,4,6,8,10]
xlabel("x-axis")
ylabel("y-axis")
title("Vertical bar graph")
bar(x, y, color="red")


horizontal bar chart


clf()
x = [10,20,30,40,50]
y = [2,4,6,8,10]
title("Horizontal bar graph")
xlabel("x-axis")
ylabel("y-axis")
barh(x,y,color="red")

2D histogram


clf()
x = rand(1000)
y = rand(1000)
xlabel("x-axis")
ylabel("y-axis")
title("2D Histograph")
hist2D(x, y, bins=50)

pie chart


clf()
labels = ["Fruits";"Vegetables";"Wheat"]
colors = ["Orange";"Blue";"Red"]
sizes = [25;40;35]
explode = zeros(length(sizes))
fig = figure("piechart", figsize=(10,10))
p = pie(sizes, labels=labels, shadow=true, startangle=90, colors = colors)
title("Pie charts")


Scatter chart


clf()
fig = figure("scatterplot", figsize = (10,10))
x = rand(50)
y = rand(50)
areas = 1000*rand(50);
scatter(x, y, s=areas, alpha=0.5)
xlabel("x-axis")
ylabel("y-axis")
title("Scatter Plot")



PyPlot 的 3D plot 是使用 surf(x, y, z, facecolors=colors)


參數 說明
X,Y,Z Data values as 2D arrays
rstride Array row stride (step size)
cstride Array column stride (step size)
rcount Use at most this many rows, defaults to 50
ccount Use at most this many columns, defaults to 50
color Color of the surface patches
cmap A colormap for the surface patches.
facecolors Face colors for the individual patches
norm An instance of Normalize to map values to colors
vmin Minimum value to map
vmax Maximum value to map
shade Whether to shade the facecolors

using PyPlot

clf()
a = range(0.0, stop=2pi, length=500)
b = range(0.0, stop=2pi, length=500)

len_a = length(a)
len_b = length(b)

x = ones(len_a, len_b)
y = ones(len_a, len_b)
z = ones(len_a, len_b)

for i=1:len_a
    for j=1:len_b
        x[i,j] = sin(a[i])
        y[i,j] = cos(a[i])
        z[i,j] = sin(b[j])
    end
end

colors = rand(len_a, len_b, 3)
fig = figure()
surf(x, y, z, facecolors=colors)
fig[:canvas][:draw]()


Gadfly


這是一個圖形的 library,可以輸出圖片為 SVG, PNG, PostScript, PDF,也可用 IJulia 運作,跟 DataFrames 緊密整合,提供 pan, zoom, toggle 的功能。執行 Gadfly.plot 後,browser 會打開一個 html 檔案,裡面是 svg 圖片。


Pkg.add("Gadfly")
using Gadfly
Gadfly.plot(x = rand(10), y=rand(10))


# 折線圖
Gadfly.plot(x = rand(10),y=rand(10), Geom.point, Geom.line)

Gadfly.plot(x=1:10, y=[10^n for n in rand(10)], Scale.y_sqrt, Geom.point, Geom.smooth, Guide.xlabel("x"), Guide.ylabel("y"), Guide.title("Graph with labels"))




Plotting DataFrames with Gadfly

使用 RDatasets (有一些範例資料) 產生 DataFrame for the plot function


折線圖


using RDatasets
Gadfly.plot(dataset("datasets", "iris"),
        x="SepalLength",
        y="SepalWidth",
        Geom.line)


Point Plot


Gadfly.plot(dataset("datasets", "iris"),
        x="SepalLength",
        y="SepalWidth",
        Geom.point)


plot a graph between SepalLength and SepalWidth



histogram


Gadfly.plot(x=randn(4000), Geom.histogram(bincount=100))


preceding showcased histogram


Gadfly.plot(dataset("mlmRev", "Gcsemv"),
        x = "Course", color="Gender", Geom.histogram)


References


Learning Julia

2019/6/10

Numerical and Scientific Computation in Julia

julia 提供處理大量資料,以及進行統計運算的 library


Working with data


首先是讀取資料的方式,如果是 binary 資料,可直接用 read(), write()


julia> for val in [:Bool, :Char, :Int8]
         @eval println(@which read(stdin, $val))
       end
read(s::IO, ::Type{Bool}) in Base at io.jl:593
read(io::IO, ::Type{Char}) in Base at io.jl:613
read(s::IO, ::Type{Int8}) in Base at io.jl:588

使用


julia> read(stdin, Char)
j
'j': ASCII/Unicode U+006a (category Ll: Letter, lowercase)

julia> read(stdin, Bool)
true
true

julia> read(stdin, Int8)
12
49

readline


julia> methods(readline)
# 4 methods for generic function "readline":
[1] readline(s::IOStream; keep) in Base at iostream.jl:433
[2] readline() in Base at io.jl:370
[3] readline(filename::AbstractString; keep) in Base at io.jl:364
[4] readline(s::IO; keep) in Base at io.jl:370

使用


julia> number = parse(Int64, readline())
12
12

julia> println(number)
12



working with text files

open 參數除了 filename,後面還有存取該檔案的 mode


julia> methods(open)
# 8 methods for generic function "open":
[1] open(fname::AbstractString; read, write, create, truncate, append) in Base at iostream.jl:275
[2] open(fname::AbstractString, mode::AbstractString) in Base at iostream.jl:339
[3] open(f::Function, cmds::Base.AbstractCmd, args...) in Base at process.jl:615
[4] open(f::Function, args...; kwargs...) in Base at iostream.jl:367
[5] open(cmds::Base.AbstractCmd) in Base at process.jl:584
[6] open(cmds::Base.AbstractCmd, mode::AbstractString) in Base at process.jl:562
[7] open(cmds::Base.AbstractCmd, mode::AbstractString, other::Union{RawFD, FileRedirect, IO}) in Base at process.jl:562
[8] open(cmds::Base.AbstractCmd, other::Union{RawFD, FileRedirect, IO}; write, read) in Base at process.jl:584

Mode Description
r read
r+ read, write
w write, create, truncate
w+ read, write, create, truncate
a write, create, append
a+ read, write, create, append

# 有個文字檔 sample.txt
shell> cat sample.txt

file = open("sample.txt")

# 以行為單位,讀入文字檔
file_data = readlines(file)

enumerate(file_data)

# 加上行號
for lines in enumerate(file_data)
   println(lines[1],"-> ", lines[2])
end

# 大寫列印
for line in file_data
   println(uppercase(line))
end

# 反過來列印
for line in file_data
   println(reverse(line))
end

# 計算行數
countlines("sample.txt")

# 列印第一行
first(file_data)

# 最後一行
last(file_data)

working with CSV

using DelimitedFiles

csvfile = readdlm("sample.csv", ',', String, '\n')

# 只取得第二欄資料
csvfile[:,2]

# 只取前三行資料
csvfile[1:3,:]

# 以 | 區隔資料的 sample.psv
# "Lora"|"UK"
# "James"|"UK"
readdlm("sample.psv",'|')

working with DataFrames

DataFrame 是一種類似 database 的資料結構,可以用類似 SQL 的方式存取 DataFrames


using DataFrames

# 取得所有 DataFrames 支援的 functions
names(DataFrames)

DataFrame: 2D data structure,類似 R 與 Pandas 的 DataFrame


  • DataArray: 比 julia 預設 Array type 提供更多 comparison 的功能,但目前已經 deprecated (ref: https://github.com/JuliaStats/DataArrays.jl)
  • DataFrame: 2D data structure,類似 R 與 Pandas 的 DataFrame



julia 的 Array 以 nothing 代表 missing value


julia> a = [1,2,3,nothing,5,6]
6-element Array{Union{Nothing, Int64},1}:
 1
 2
 3
  nothing
 5
 6

julia> typeof(a[4])
Nothing



DataFrame: https://juliadata.github.io/DataFrames.jl/stable/man/getting_started.html


julia> dframe = DataFrame(Names = ["John","May"], Age = [27,28])
2×2 DataFrame
│ Row │ Names  │ Age   │
│     │ String │ Int64 │
├─────┼────────┼───────┤
│ 1   │ John   │ 27    │
│ 2   │ May    │ 28    │

julia> dframe.Names
2-element Array{String,1}:
 "John"
 "May"

julia> dframe.Age
2-element Array{Int64,1}:
 27
 28

julia> names(dframe)
2-element Array{Symbol,1}:
 :Names
 :Age

julia> describe(dframe)
2×8 DataFrame
│ Row │ variable │ mean   │ min  │ median │ max │ nunique │ nmissing │ eltype   │
│     │ Symbol   │ Union… │ Any  │ Union… │ Any │ Union…  │ Nothing  │ DataType │
├─────┼──────────┼────────┼──────┼────────┼─────┼─────────┼──────────┼──────────┤
│ 1   │ Names    │        │ John │        │ May │ 2       │          │ String   │
│ 2   │ Age      │ 27.5   │ 27   │ 27.5   │ 28  │         │          │ Int64    │



另外有個獨立的 CSV 套件,可處理 csv file,讀入 CSV file 後,就得到 DataFrame 物件


using Pkg
Pkg.add("CSV")
using CSV

julia> CSV.read("sample.csv")
3×2 DataFrame
│ Row │ Lora    │ UK      │
│     │ String⍰ │ String⍰ │
├─────┼─────────┼─────────┤
│ 1   │ James   │ UK      │
│ 2   │ Raj     │ India   │
│ 3   │ May     │ America │

Linear algebra


產生 matrix


# 亂數 3x3 matrix
julia> A = rand(3,3)
3×3 Array{Float64,2}:
 0.108282  0.433033  0.247145
 0.571936  0.369386  0.547845
 0.423382  0.380503  0.77661

# array 且初始為 1
julia> ones(5)
5-element Array{Float64,1}:
 1.0
 1.0
 1.0
 1.0
 1.0



Vector 與 Matrix 的差異


Vector{T} 是 Array{T, 1} 的 alias,Matrix{T} 是Array{T, 2} 的 alias


julia> Vector{Float64} == Array{Float64,1}
true

julia> Matrix{Float64} == Array{Float64,2}
true



矩陣乘法


julia> A = rand(3,3)
3×3 Array{Float64,2}:
 0.167005  0.188954  0.0483164
 0.82603   0.440255  0.00107621
 0.137211  0.308508  0.724953

julia> b = 2*A
3×3 Array{Float64,2}:
 0.334011  0.377909  0.0966328
 1.65206   0.88051   0.00215241
 0.274422  0.617015  1.44991

julia> b= 2A
3×3 Array{Float64,2}:
 0.334011  0.377909  0.0966328
 1.65206   0.88051   0.00215241
 0.274422  0.617015  1.44991



transpose 轉置矩陣


julia> transpose_of_A = A'
3×3 LinearAlgebra.Adjoint{Float64,Array{Float64,2}}:
 0.167005   0.82603     0.137211
 0.188954   0.440255    0.308508
 0.0483164  0.00107621  0.724953



inverse 逆矩陣


julia> inv(A)
3×3 Array{Float64,2}:
 -6.31559   2.41816    0.417329
 11.8591   -2.26692   -0.787013
 -3.85134   0.507016   1.63533



Determinant 行列式


julia> using LinearAlgebra

julia> det(A)
-0.05048337143385562



Eigenvalues 特徵向量


julia> eigvals(A)
3-element Array{Float64,1}:
 -0.1016764648907107
  0.5846559789763167
  0.8492342814186749



方程式運算


julia> 5
5

julia> equation = 3x^2 + 4x + 3
98

Differential calculus


Pkg.add("Calculus")
using Calculus
names(Calculus)

julia> f(x) = sin(x)
f (generic function with 1 method)
        
julia> f'(1.0)
0.5403023058631036

julia> f'(1.0) - cos(1.0)
-5.036193684304635e-12

julia> f''(1.0) - (-sin(1.0))
-6.647716624952338e-7

julia> differentiate("cos(x) + sin(x) + exp(-x) * cos(x)", :x)
:(1 * -(sin(x)) + 1 * cos(x) + ((-1 * exp(-x)) * cos(x) + exp(-x) * (1 * -(sin(x)))))

julia> differentiate("sin(x)", :x)
:(1 * cos(x))

julia> differentiate("cos(x) + sin(y) + exp(-x) * cos(y)", [:x, :y])
2-element Array{Any,1}:
 :(1 * -(sin(x)) + ((-1 * exp(-x)) * cos(y) + exp(-x) * 0))
 :(1 * cos(y) + (0 * cos(y) + exp(-x) * (1 * -(sin(y)))))

Statistics


JuliaStats 所列出支援的 packages


  • DataFrames
  • Distributions: probability distribution
  • MultivariateStats: Multivariate statistical analysis
  • HypothesisTests
  • MLBase: Swiss knife for machine learning
  • Distances: Various distances between vectors
  • KernelDensity
  • Clustering: algorithm for data clustering
  • GLM: Generalized linear models
  • NMF: Nonnegative matrix factorization
  • RegERMs: Regularized empirical risk minimization
  • MCMC: Markov Chain Monte Carlo
  • TimeSeries: time series analysis



simple statistics

julia> using Statistics

julia> x = [10,20,30,40,50]

julia> mean(x)
30.0

# 中位數 median
julia> median(x)
30.0

julia> sum(x)
150

# 標準差
julia> std(x)
15.811388300841896

# variance 變異數
julia> var(x)
250.0

julia 也支援 cumulative operations 的 functions


  • accumulate
  • cumsum(): cumulative summation
  • cumprod(): cumulative product

julia> accumulate(+, x)
5-element Array{Int64,1}:
  10
  30
  60
 100
 150

julia> accumulate(-, x)
5-element Array{Int64,1}:
   10
  -10
  -40
  -80
 -130

julia> cumsum(x)
5-element Array{Int64,1}:
  10
  30
  60
 100
 150

julia> cumprod(x)
5-element Array{Int64,1}:
       10
      200
     6000
   240000
 12000000

julia> for i in [:cumsum,:cumprod]
               @eval print($i, "->")
               @eval println($i(x))
       end
cumsum->[10, 30, 60, 100, 150]
cumprod->[10, 200, 6000, 240000, 12000000]



statistics using DataFrames

julia> using DataFrames

julia> dframe = DataFrame(Subjects = ["Maths","Physics","Chemistry"],Marks = [90,85,95])
3×2 DataFrame
│ Row │ Subjects  │ Marks │
│     │ String    │ Int64 │
├─────┼───────────┼───────┤
│ 1   │ Maths     │ 90    │
│ 2   │ Physics   │ 85    │
│ 3   │ Chemistry │ 95    │

julia> describe(dframe)
2×8 DataFrame
│ Row │ variable │ mean   │ min       │ median │ max     │ nunique │ nmissing │ eltype   │
│     │ Symbol   │ Union… │ Any       │ Union… │ Any     │ Union…  │ Nothing  │ DataType │
├─────┼──────────┼────────┼───────────┼────────┼─────────┼─────────┼──────────┼──────────┤
│ 1   │ Subjects │        │ Chemistry │        │ Physics │ 3       │          │ String   │
│ 2   │ Marks    │ 90.0   │ 85        │ 90.0   │ 95      │         │          │ Int64    │



Pandas

對習慣使用 python 進行資料分析的使用者來說,Pandas 是比較常用的 package


julia> pandasDataframe = Pandas.DataFrame(Dict(:Subjects => ["Maths","Physics","Chemistry"],:Marks => [90,85,95]))
   Marks   Subjects
0     90      Maths
1     85    Physics
2     95  Chemistry


julia> Pandas.describe(pandasDataframe)
       Marks
count    3.0
mean    90.0
std      5.0
min     85.0
25%     87.5
50%     90.0
75%     92.5
max     95.0


julia> pandasDataframe[:Subjects]
0        Maths
1      Physics
2    Chemistry
Name: Subjects, dtype: object


julia> pandasDataframe[:Marks]
0    90
1    85
2    95
Name: Marks, dtype: int64


julia> query(pandasDataframe,:(Marks>90))
   Marks   Subjects
2     95  Chemistry



Distributions

distributions.jl 有以下功能


  • Moments (ex: mean, variance, skewness, and kurtosis), entropy, and other properties
  • Probability density/mass functions (pdf) and their logarithms (logpdf)
  • Moment generating functions and characteristic functions
  • Maximum likelihood estimation
  • Posterior w.r.t. conjugate prior and Maximum-A-Posteriori (MAP) estimation

using Pkg
Pkg.add("Distributions")
using Distributions

distribution = Normal()

# 以 normal distribution 產生 10 筆 random 資料
x = rand(distribution, 10)

Binomial()

Cauchy()

Poisson()



TimeSeries

Pkg.add("TimeSeries")
Pkg.add("MarketData")

using TimeSeries

julia> dates  = collect(Date(2017,8,1):Day(1):Date(2017,8,5))
5-element Array{Date,1}:
 2017-08-01
 2017-08-02
 2017-08-03
 2017-08-04
 2017-08-05

julia> sample_time = TimeArray(dates, rand(length(dates)))
5×1 TimeArray{Float64,1,Date,Array{Float64,1}} 2017-08-01 to 2017-08-05
│            │ A      │
├────────────┼────────┤
│ 2017-08-01 │ 0.9142 │
│ 2017-08-02 │ 0.0834 │
│ 2017-08-03 │ 0.417  │
│ 2017-08-04 │ 0.4778 │
│ 2017-08-05 │ 0.6859 │



Hypothesis testing

測試 sample data 是否有足夠的 evidence,針對整個 population of data 進行條件測試。


有兩種 hypothesis testing 測試方式


  • Null hypothesis: the statement being tested
  • Alternative hypothesis: the statement that you will be able to conclude as true

Pkg.add("HypothesisTests")
using HypothesisTests

using Distributions

julia> sampleOne = rand(Normal(), 10)
10-element Array{Float64,1}:
 -0.5347603532683008
 -0.7882658160278007
 -0.3314222340035204
 -0.9280782524368908
  0.4540819395751322
  1.056554282551302
  1.2211198338710754
 -0.7067184060685551
  0.9788402691232629
  0.39421862072760827

julia> testOne = OneSampleTTest(sampleOne)
One sample t-test
-----------------
Population details:
    parameter of interest:   Mean
    value under h_0:         0
    point estimate:          0.0815569884043313
    95% confidence interval: (-0.514, 0.6771)

Test summary:
    outcome with 95% confidence: fail to reject h_0
    two-sided p-value:           0.7638

Details:
    number of observations:   10
    t-statistic:              0.3097695342286937
    degrees of freedom:       9
    empirical standard error: 0.2632827937950805


julia> @which OneSampleTTest(sampleOne)
OneSampleTTest(v::AbstractArray{T,1}) where T<:Real in HypothesisTests at /Users/charley/.julia/packages/HypothesisTests/M3Ysg/src/t.jl:98

julia> pvalue(testOne)
0.7637885831202397

julia> pvalue(testOne, tail=:right)
0.38189429156011984

julia> pvalue(testOne, tail=:left)
0.6181057084398802

# check whether 25 successes from 1000 samples is inconsistent with a 50% success rate
julia> BinomialTest(25, 1000, 0.50)
Binomial test
-------------
Population details:
    parameter of interest:   Probability of success
    value under h_0:         0.5
    point estimate:          0.025
    95% confidence interval: (0.0162, 0.0367)

Test summary:
    outcome with 95% confidence: reject h_0
    two-sided p-value:           <1e-99

Details:
    number of observations: 1000
    number of successes:    25

Optimization


optimization 是 finding best solution from all feasible solutions 的問題,可分為兩類


  • continuous optimization problem
  • combinatorial optimization problem (discrete)

某些問題可以用 optimization 方法解決


  • Shortest path
  • Maximum flow through a network
  • Vehicle routing

juila 將 optimization packages 集合在 JuliaOpt,其中有兩個最重要的 packages,這兩個都是 AML(Algebraic modeling languages),放在 MathProgBase.jl 裡面


  • JuMP (Julia for Mathematical Programming)
  • Convex.jl



JuMP

Python 習慣使用 PuLP


Pkg.add("JuMP")
Pkg.add("Clp")
using JuMP
using Clp

julia> m = JuMP.Model()
Feasibility problem with:
 * 0 linear constraints
 * 0 variables
Solver is default solver

julia> m = JuMP.Model(solver = Clp.ClpSolver())
Feasibility problem with:
 * 0 linear constraints
 * 0 variables
Solver is Clp



optimiser.jl


using JuMP
using Clp

m = Model(solver = ClpSolver())
@variable(m, 0 <= a <= 2 )
@variable(m, 0 <= b <= 10 )

@objective(m, Max, 5a + 3*b )
@constraint(m, 1a + 5b <= 3.0 )

print(m)

status = solve(m)

println("Objective value: ", getobjectivevalue(m))
println("a = ", getvalue(a))
println("b = ", getvalue(b))

執行


$ julia optimiser.jl
Max 5 a + 3 b
Subject to
 a + 5 b ≤ 3
 0 ≤ a ≤ 2
 0 ≤ b ≤ 10
Objective value: 10.6
a = 2.0
b = 0.2

Convex.jl

用在 disciplined convex programming,使用 Convex 需要 solver,也就是 SCS


Pkg.add("Convex")
Pkg.add("SCS")

using Convex
using SCS

X = Variable(2, 2)

y = Variable()

p = minimize(vecnorm(X) + y, 2 * X <= 1, X' + y >= 1, X >= 0, y >= 0)

solve!(p)

println(X.value)

println(y.value)

p.optval

References


Learning Julia

2019/6/3

Interoperability and Meta Programming


julia 可跟 C, Python 的程式互動。另外 juila 支援 meta programming 的形式。


Interacting with OS


在 REPL 可用 ; 進入 shell,執行 shell commands,如果在 julia,則是直接用 pwd()


shell> pwd
/Users/user

julia> pwd()
"/Users/user"



filesystem operations

存取檔案的 functions


  • homedir(), joinpath()


    為支援 linux, windows,使用 joinpath() 產生檔案的路徑


julia> homedir()
"/Users/user"

julia> joinpath(homedir(), "Documents")
"/Users/user/Documents"

  • pwd(), cd()


    取得目前的目錄,以及切換目錄


    cd("../")
  • readdir()


    取得目錄內的檔案列表,包含目錄及檔案


    readdir(".")
  • mkdir()


    d = joinpath(homedir(), "LearningJulia")
    mkdir(d)
  • stat


    stat("somefile") 會取得 StatStruct(mode=0o100644, size=28676),而 StatStruct 裡面有這些欄位


    ref: https://github.com/JuliaLang/julia/blob/master/base/stat.jl


    ex: stat("somefile").size


    Name Description
    size The size (in bytes) of the file
    device ID of the device that contains the file
    inode The inode number of the file
    mode The protection mode of the file
    nlink The number of hard links to the file
    uid The user id of the owner of the file
    gid The group id of the file owner
    rdev If this file refers to a device, the ID of the device it refers to
    blksize The file-system preferred block size for the file
    blocks The number of such blocks allocated
    mtime Unix timestamp of when the file was last modified
    ctime Unix timestamp of when the file was created

    • cp, mv

    julia> cp("test", "test1")
    "test1"
    
    julia> isfile("test1")
    true
    
    julia> mv("test1", "test2")
    "test2"

  • isdir, homedir, basename, dirname, and splitdir


    julia> homedir()
    "/Users/user"
    
    julia> joinpath(homedir(), "Documents")
    "/Users/user/Documents"
    
    julia> isdir(joinpath(homedir(), "Documents"))
    true
    
    julia> basename(homedir())
    "user"
    
    julia> dirname(homedir())
    "/Users"
    
    julia> splitdir(homedir())
    ("/Users", "user")
    
  • mkpath, ispath, abspath, and joinpath


    julia> ispath(homedir())
    true
    
    julia> abspath(".")
    "/Users/user/Downloads/"
    
    julia> joinpath(homedir(), "Documents")
    "/Users/user/Documents"
    
    julia> mkpath(joinpath("Users","adm"))
    "Users/adm"
    
    julia> for (root, dirs, files) in walkdir("Users")
                   println("Directories in $root")
           end
    Directories in Users
    Directories in Users/adm



I/O Operations

STDOUT, STDERR, STDIN 是三個 global variables,分別為 standard output, error, input stram


open(), close(), write, read


julia> file = open("sample.txt")
IOStream(<file sample.txt>)

julia> file
IOStream(<file sample.txt>)

julia> lines = readlines(file)
2-element Array{String,1}:
 "Hi there!"
 "Learning Julia is so much fun."

julia> write("sample.txt", "hi how are you doing?")
21

julia> read("sample.txt")
21-element Array{UInt8,1}:

julia> readline("sample.txt")
"hi how are you doing?"

julia> close(file)



讀取某個文字檔,計算裡面有幾個 "Julia" 這個 word


# Arguments
# ARGS[0] is the command itself
in_file = ARGS[1]
out_file = ARGS[2]

# Keeping track using a counter
counter = 0
for line in eachline(in_file)
    for word in split(line)
        if word == "Julia"
            global counter += 1
        end
    end
end

# Write the contents to the o/p file
write(out_file, "The count for the word julia is $counter")

# Finally, read the contents to inform the user
for line in readlines(out_file)
    println(line)
end

shell> julia sample.jl sample.txt out.txt
The count for the word julia is 4

Calling C and Python


Calling C from Julia

compile (ex: LLVM) 需要知道什麼,才能由 Julia 呼叫 C


  • Name of the library
  • Name of the function
  • Number and types of the arguments (也稱為 Arity)
  • return type of the function
  • values of the arguments passed

julia 使用 ccall((:name,"lib"), return_type, (arg1_type, arg2_type...), arg1, arg2) 處理


呼叫 C 標準函式庫的 clock function


julia> ccall((:clock, :libc), Int64, ())
3206897

julia> ccall((:clock, :libc), Cint, ())
3213482

julia> Int32 == Cint
true

Cint 是 C 的資料型別,等於 signed int c-type,另外還有 Cint, Cuint, Clong, Culong, and Cchar




呼叫 getenv,取得 SHELL value,Ptr{Cchar} 是參數的資料型別,後面 return value 資料型別也是 Ptr{Cchar}


julia> syspath = ccall( (:getenv, :libc), Ptr{Cchar}, (Ptr{Cchar},), "SHELL")
Ptr{Int8} @0x00007ffee37b857a

julia> unsafe_string(syspath)
"/bin/bash"

C 的 struct 可以替換為 julia 的 composite types


Calling Python form Julia

使用 PyCall


julia> using Pkg

julia> Pkg.add("PyCall")

julia> using PyCall

julia> py"len('julia')"
5

julia> py"str(5)"
"5"

julia> py"""
       print('hello world')
       """
hello world



如果要使用 python 的 built-in data type (ex: dict),可使用 pybuiltin


julia> pybuiltin(:dict)(a=1,b=2)
Dict{Any,Any} with 2 entries:
  "b" => 2
  "a" => 1

julia> d = pycall(pybuiltin("dict"), Any, a=1, b=2)
PyObject {'b': 2, 'a': 1}

julia> typeof(d)
PyObject

# 利用 PyDict 轉換為 julia dict object
julia> julia_dictionary = PyDict{Symbol, Int64}(pycall(pybuiltin("dict"), Any, a=1, b=2))
PyDict{Symbol,Int64,true} with 2 entries:
  :b => 2
  :a => 1

julia> typeof(julia_dictionary)
PyDict{Symbol,Int64,true}

julia> julia_dictionary[:a]
1

# 產生一個 kw 參數的 function
julia> f(; a=0, b=0) = [10a, b]
f (generic function with 1 method)

# 以 dict 呼叫 function
julia> f(;julia_dictionary...)
2-element Array{Int64,1}:
 10
  2

Expressions


這是 metaprogramming 的功能,這是參考 LISP 的功能


首先說明 julia 如何 interprets a code


julia> code = "println(\"hello world \")"
"println(\"hello world \")"

julia> expression = Meta.parse(code)
:(println("hello world "))

julia> typeof(expression)
Expr

julia> expression.args
2-element Array{Any,1}:
 :println
 "hello world "

julia> expression.head
:call

julia> dump(expression)
Expr
  head: Symbol call
  args: Array{Any}((2,))
    1: Symbol println
    2: String "hello world "

產生 expression,用 eval 運算, :call 是 symbol,表示 head of the expression


julia> sample_expr = Expr(:call, +, 10, 20)
:((+)(10, 20))

julia> eval(sample_expr)
30

julia> sample_expr.args
3-element Array{Any,1}:
   +
 10
 20

將參數替換為 :x, :y 變數,也可以直接寫 x, y


julia> x = 10; y =10
10

julia> sample_expr = Expr(:call, +, :x, :y)
:((+)(x, y))

julia> sample_expr = Expr(:call, +, x, y)
:((+)(10, 10))

julia> eval(sample_expr)
20

也可以使用 $


julia> x = 10; y=10
10

julia> e = :($x + $y)
:(10 + 10)

julia> eval(e)
20

所以有 : 跟 $ 兩種方式可產生 Expr object


  • Using quotes(:) at runtime
  • Using dollar($) ar parse time

另外還有一個方式,是使用 quote 這個 keyword。quote 跟 : 的差別,是用 quote 可讓程式碼排列更好,比較容易實作


julia> quote
          30 * 100
       end
quote
    #= REPL[88]:2 =#
    30 * 100
end

julia> eval(ans)
3000

julia> :(30 * 100)
:(30 * 100)

julia> eval(ans)
3000

Macros


類似 function,但 function 使用 variables 為參數,而 macros 使用 expressions,並回傳 modified expressions,呼叫 macro 是用 @


macro NAME
    # some custom code
    # return modified expression
end

因為 REPL 建立的 macro 是在 Main module 裡面


julia> macro HELLO(name)
         :( println("Hello! ", $name))
       end
@HELLO (macro with 1 method)

julia> @HELLO("world")
Hello! world

julia> macroexpand(Main, :(@HELLO("world")))
:((Main.println)("Hello! ", "world"))



why metaprogramming?

metaprogramming 可省略很多重複的程式碼


for sym in [:foo, :bar, :baz]
    @eval function $(Symbol(sym))(n::Int64)
        for i in 1:n
            println( $(string(sym)) )
        end
    end
end

可這樣使用


foo(1)
bar(2)
baz(3)



for header in [:h1, :h2, :h3, :h4, :h5, :h6]
     @eval function $(Symbol(header))(text::String)
         println("<" * $(string(header))* ">"  * " $text " * "</" * $(string(header))* ">")
     end
 end

h1("Hello world!")
# <h1> Hello world! </h1>

h3("Hello world!")
# <h3> Hello world! </h3>



Built-in macros

以下是所有內建的 macros


julia> @
@MIME_str      @boundscheck    @edit           @html_str       @nospecialize   @text_str
@__DIR__       @cfunction      @elapsed        @inbounds       @polly          @threadcall
@__FILE__      @cmd            @enum           @info           @r_str          @time
@__LINE__      @code_llvm      @error          @inline         @raw_str        @timed
@__MODULE__    @code_lowered   @eval           @int128_str     @s_str          @timev
@__dot__       @code_native    @evalpoly       @isdefined      @show           @uint128_str
@allocated     @code_typed     @fastmath       @label          @simd           @v_str
@assert        @code_warntype  @functionloc    @less           @specialize     @view
@async         @debug          @generated      @macroexpand    @static         @views
@b_str         @deprecate      @gensym         @macroexpand1   @sync           @warn
@big_str       @doc            @goto           @noinline       @task           @which

  • @time


    可取得執行某一段程式的耗費時間


    julia> function recursive_sum(n)
              if n == 0
                  return 0
              else
                  return n + recursive_sum(n-1)
              end
           end
    recursive_sum (generic function with 1 method)
    
    julia> @time recursive_sum(10000)
      0.005359 seconds (3.22 k allocations: 183.158 KiB)
    50005000
  • @elapsed


    類似 @time,但只有回傳時間 in Float64


    julia> @elapsed recursive_sum(10000)
    3.0984e-5
    
    julia> @elapsed recursive_sum(10000)
    2.4597e-5
  • @show


    會回傳 expression


    julia> @show(println("hello world"))
    hello world
    println("hello world") = nothing
    
    julia> @show(:(println("hello world")))
    $(Expr(:quote, :(println("hello world")))) = :(println("hello world"))
    :(println("hello world"))
    
    julia> @show(:(3*2))
    $(Expr(:quote, :(3 * 2))) = :(3 * 2)
    :(3 * 2)
    
    julia> @show(3*2)
    3 * 2 = 6
    6
    
    julia> @show(Int64)
    Int64 = Int64
    Int64
  • @which


    如果有某個 function 有多個 methods,也就是 multiple dispatch 的功能,想知道會呼叫哪一個 method


    julia> function tripple(n::Int64)
              3n
           end
    tripple (generic function with 1 method)
    
    julia> function tripple(n::Float64)
              3n
           end
    tripple (generic function with 2 methods)
    
    julia> methods(tripple)
    # 2 methods for generic function "tripple":
    [1] tripple(n::Float64) in Main at REPL[11]:2
    [2] tripple(n::Int64) in Main at REPL[10]:2
    
    julia> @which tripple(10)
    tripple(n::Int64) in Main at REPL[10]:2
    
    julia> @which tripple(10.0)
    tripple(n::Float64) in Main at REPL[11]:2
  • @task


    類似 coroutine,用來產生一個 task,而不是直接執行


    julia> say_hello() = println("hello world")
    say_hello (generic function with 1 method)
    
    julia> say_hello_task = @task say_hello()
    Task (runnable) @0x0000000113ed9210
    
    julia> istaskstarted(say_hello_task)
    false
    
    julia> schedule(say_hello_task)
    hello world
    Task (queued) @0x0000000113ed9210
    
    julia> yield()
    
    julia> istaskdone(say_hello_task)
    true
  • @codellvm, @codelowered, @codetyped,@codenative, and @code_warntype


    瞭解 code 在 julia 中的所有形式


    function fibonacci(n::Int64)
       if n < 2
           n
       else 
           fibonacci(n-1) + fibonacci(n-2)
       end
    end
    
    fibonacci(n::Int64) = n < 2 ? n : fibonacci(n-1) + fibonacci(n-2)
    
    # 轉換為 single static assignment,每個變數只會被 assigned 一次,在使用變數前都會先定義
    @code_lowered fibonacci(10)
    
    # 
    @code_typed fibonacci(10)
    
    @code_warntype fibonacci(10)
    
    # 使用 LLVM C++ API 產生 LLVM intermediate representation
    @code_llvm fibonacci(10)
    
    # binary code in memory
    @code_native fibonacci(10)
    

Type introspection


首先定義新的 type: Student,產生兩個物件


struct Student
   name::String
   age::Int64
end

alpha = Student("alpha",24)

beta = Student("beta",25)

可檢查物件的資料型別,或是使用 isa 判斷是否為某個 function 產生的 type


julia> typeof(alpha)
Student

julia> isa(alpha, Student)
true

julia> alpha isa Student
true

reflection


可在 runtime 查詢物件的 attributes。在 julia 產生 function 後,就可以查詢 function 有幾個參數,有哪些 methods。


function calculate_quad(a::Int64,b::Int64,c::Int64,x::Int64)
   return a*x^2 + b*x + c
end

calculate_quad(1,2,3,4)

function calculate_quad(a::Int64,b::Int64,c::Int64,x::Float64)
   return a*x^2 + b*x + c
end

calculate_quad(1,2,3,4.75)

julia> methods(calculate_quad)
# 2 methods for generic function "calculate_quad":
[1] calculate_quad(a::Int64, b::Int64, c::Int64, x::Float64) in Main at REPL[38]:2
[2] calculate_quad(a::Int64, b::Int64, c::Int64, x::Int64) in Main at REPL[36]:2

julia> fieldnames(Student)
(:name, :age)

julia> Student.types
svec(String, Int64)

julia> typeof(Student.types)
Core.SimpleVector

References


Learning Julia

2019/5/27

Control Flow in Julia


conditional evaluation


compound expression,將一連串的 code 合併起來,確保會依照順序運算,除了換行的方式,還可以用 ; 區隔,寫在同一行


julia> volume = begin
          len = 10
          breadth = 20
          height = 30
          len * breadth * height
       end
6000

julia> volume = (length = 10; breadth = 20; height = 30; length * breadth * height)
6000



conditional evaluation


FizzBuzz algorithm,用 if, elseif, else 撰寫條件


for i in 1:30
   if i % 3 == 0 && i % 5 == 0
       println("FizzBuzz")
   elseif i % 3 == 0
       println("Fizz")
   elseif i % 5 == 0
       println("Buzz")
   else
       println(i)
   end
end



計算是否為質數的 function


function factors(num::Int64)
   factors = []
   for i in 1:num
       if rem(num, i) == 0
           push!(factors, i)
       end
   end
   return factors
end

function is_prime(num::Int64)
   factors_array = factors(num)
   if length(factors_array) == 2
       true
   else
       false
   end
end



if 區塊裡面的變數,在區塊外面還可以使用,這表示 if block 並沒有 local scope


function f(n)
   if n % 2 == 0
       parity = "even"
   else
       parity = "odd"
   end
   println("the number is $parity")
end



if block 結束時,會 return value


julia> x = if true
               2
       end
2

julia> x = if true
               println("test")
       end
test

julia> x == nothing
true



ternary operators


condition ? do this, if true : do this, if false


julia> name = "julia"
"julia"

julia> isa(name, String) ? "its a string" : "nopes, not a string"
"its a string"



short circuit evalation


  • var1 && var2,只有在 var1 為 true,才會運算 var2
  • var1 || var2,當 var1 為 false,才會運算 var2

julia> all(isdigit, "10") && println("reached me")
reached me

julia> all(isdigit, "ten") && println("reached me")
false

julia> all(isdigit, "ten") || println("reached me")
reached me

repeated evaluation


有兩種: while, for


collection = [1,2,3,4,5,6,7,8,9]
while length(collection) > 1
   pop!(collection)
   println(collection)
end

for


statement = "This is a great example!"
for word in split(statement)
   println(word)
end

# split 後,取第 2~4 個元素
for word in split(statement)[2:4]
   println(word)
end

for word in split(statement)[2:3:4]
   println(word)
end
# is

defining range


range expression 1:5


julia> for i in 1:5
          print("*",i,"\n", "\t"^i)
       end
*1
    *2
        *3
            *4
                *5

5:-1:1表示為 5 到 1,每一次 減1


julia> for i in 1:5
          for j in 1:i
              print("*")
          end
          println("")
       end
*
**
***
****
*****

julia> for i in 5:-1:1
          for j in 1:i
              print("*")
          end
          println("")
       end
*****
****
***
**
*

reverse a string


julia> my_string = "This is a great thing to do!"
"This is a great thing to do!"

julia> my_string[length(my_string):-1:1]
"!od ot gniht taerg a si sihT"

break and continue


word="julia"
for letter in word
   if letter == 'i'
       break
   end
   println(letter)
end

# continue 跳過此次迴圈,繼續下一個
for letter in word
   if letter == 'l'
       continue
   end
   println(letter)
end



Exception handling


error 跟 exception 的差異


error 是應該要避免的問題,程式不應該 catch error。程式已經知道可能會發生 exception,故在發生 exception 的條件中,可以 catch exception。


julia 提供多種 errors:


  • ArgumentError: 傳入 function 的參數,不是原本 function 期待的參數形式
  • AssertionError: 發生錯誤 (false) 的 assertion 檢查 statement
  • BoundsError: 嘗試存取 arrary 的 out-of-bounds element
  • DivideError: 除數為 0
  • DomainError: 參數在 valid domain 之外
  • EOFError: 已經到了 end of file,無法再讀取資料
  • InexactError: 再處理 exact type conversion 發生 failure
  • KeyError: 存取不存在的 key element
  • LoadError: loading file 發生 error
  • MethodError: 嘗試使用不存在的 methods
  • OutOfMemoryError: 記憶體不足
  • ReadOnlyMemoryError: 嘗試寫入 read-only memory
  • OverflowError: 當某個 operation 的 result 太大
  • ParseError: parsing expression 發生問題
  • StackOverflowError: function call 超過 call stack
  • SystemError: system call 發生 error
  • TypeError: type checking 發生 error, 傳給 function 錯誤資料型別的參數
  • UndefRefError: Unknown reference made
  • UndefVarError: Unknown reference made to a 不存在的 variable
  • InitError: 呼叫 module 的 __init__ 發生錯誤

julia 的 exception


  • ErrorException: 發生 error
  • InterruptException: 運算時發生 external interruption
  • NullException: 嘗試存取 Null
  • ProcessExitedException: process 已結束,使用 process 就會發生錯誤

julia> typeof(Exception)
DataType

julia> struct CustomException <: Exception
          var::Symbol
       end

julia> typeof(CustomException)
DataType

julia> supertype(CustomException)
Exception



throw(e)

呼叫時,會立即 throws an error


julia> throw("")
ERROR: ""
Stacktrace:
 [1] top-level scope at none:0

julia> throw(3+3)
ERROR: 6
Stacktrace:
 [1] top-level scope at none:0

julia> throw(ErrorException("error"))
ERROR: error
Stacktrace:
 [1] top-level scope at none:0

產生 TypeError


julia> function say_hi(name)
          try
              if typeof(name) != String
                  throw(TypeError(:say_hi, "printing name", String, name))
              else
                  println("hi $name")
              end
          catch e
              println(typeof(e))
          end
       end
say_hi (generic function with 1 method)

julia> say_hi('n')
TypeError

julia> say_hi("name")
hi name



error()

會產生 ErrorException


julia> function say_hi(name :: String)
               if length(name) < 5
                       error("Name less than 5!!!")
               else
                       println("hi $name")
               end
       end
say_hi (generic function with 2 methods)

julia> say_hi("joe")
ERROR: Name less than 5!!!
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] say_hi(::String) at ./REPL[59]:3
 [3] top-level scope at none:0



try/catch/finally block

用 try-catch block 封裝程式碼,攔截任何可能發生的 error


julia> try
          exponent("alpha")
       catch e
          println(e)
       finally
          print("Goodbye")
       end
MethodError(exponent, ("alpha",), 0x00000000000061d2)
Goodbye

tasks in julia


Tasks 類似 coroutines 的功能,可 suspend an operation 並在需要時 resume


julia> function producer(c::Channel)
          put!(c, "start")
          for n=1:2
              put!(c, 2n)
          end
          put!(c, "stop")
       end;

julia> chnl = Channel(producer);

julia> take!(chnl)
"start"

julia> take!(chnl)
2

julia> take!(chnl)
4

julia> take!(chnl)
"stop"

julia> take!(chnl)
ERROR: InvalidStateException("Channel is closed.", :closed)

References


Learning Julia

2019/5/20

Types and Dispatch in juila


julia 同樣也有 type system 處理 Types, Data Types,可識別 integer, string, float, Boolean。


Type system


types 是什麼?

1
1.1
'j'
"julia"

這些資料都可以直接識別出差異,分別是 integer, float, char, string。但需要一個方法讓電腦能夠識別這些資料型別。


static type vs dynamic type

有兩種方法可告訴 interpreter 資料型別是什麼


static type: 直接標記出資料型別,例如 C, C++, Java


dynamic type: interpreter 在 runitme 自動判斷資料型別,例如 Perl, Python, Ruby。雖然不指定,但內部還是會將該資料,標記為某一個資料型別


julia 同時有 static type 及 dynamic type 的功能。如果使用 static type,會讓程式運作地比較快。


Type annotations


討論 type declaration 及 conversion


:: Int64 就是將變數定義為 Int64 這個資料型別


julia> function cube(number::Int64)
        return number ^ 3
       end
cube (generic function with 1 method)

julia> cube(3)
27

實際上 :: 是個 operator,也很類似 python 的 isinstance()


julia> 2::Int64
2

julia> 2::Float64
ERROR: TypeError: in typeassert, expected Float64, got Int64



  • typeof(): type of data
  • typemax(): 該 type 可支援的最大 value
  • typemin(): 該 type 可支援的最小 value
  • bitstring(): 二進位的位元字串



  • Integer type 會根據使用的機器不同,可能是 Int8, Int16, Int32, Int64, or Int128 其中一種


    julia> typeof(1)
    Int64
    
    julia> typemax(Int64)
    9223372036854775807
    
    julia> typemin(Int64)
    -9223372036854775808
  • Float type 在 64bits 機器,是 Float64


    julia> typeof(1.1)
    Float64
    
    julia> typemax(Float64)
    Inf
    
    julia> typemin(Float64)
    -Inf
  • Char type

  • String type

  • Bool type




isa(x, type) -> Bool 判斷 x 資料型別是否為 type


julia> isa(5, Int64)
true

julia> isa(5.5, Float64)
true



type conversions

convert(type, x) 可將 x 轉換資料型別為 type


julia> convert(Float64, 10)
10.0

julia> convert(Int64, 128.0)
128

julia> convert(Int64, 128.3)
ERROR: InexactError: Int64(Int64, 128.3)
Stacktrace:
 [1] Type at ./float.jl:700 [inlined]
 [2] convert(::Type{Int64}, ::Float64) at ./number.jl:7
 [3] top-level scope at none:0

rounding: ceil, floor, round


julia> ceil(Int, 3.4)
4

julia> floor(Int, 3.4)
3

julia> round(Int, 3.4)
3

julia> round(Int, 3.6)
4

subtypes and supertypes


Number 是 Any 的 subtype,Any 是 Number 的 supertype


                      Any
                       |
     ---------------------------------------------
     Number                          AbstractString
        |                                   |
----------------                            |
Complex       Real                          |
                                            |
                                            |
         ----------------------------------------------------------
        |           |           |                     |            |
UTF8String    UTF16String     DirectIndexString   RepString    RopeString

Any 是所有資料型別的起點


julia> supertype(Number)
Any

julia> supertype(Any)
Any

julia> typeof(Any)
DataType

julia> subtypes(Number)
2-element Array{Any,1}:
 Complex
 Real



recursive 找出所有子類別


julia> function check_all_subtypes(T, space=0)
                  println("\t" ^ space, T)
                  for t in subtypes(T)
                      if t!= Any
                      check_all_subtypes(t, space+1)
                  end
              end
              end
check_all_subtypes (generic function with 2 methods)

julia> check_all_subtypes(Number)
Number
    Complex
    Real
        AbstractFloat
            BigFloat
            Float16
            Float32
            Float64
        AbstractIrrational
            Irrational
        Integer
            Bool
            Signed
                BigInt
                Int128
                Int16
                Int32
                Int64
                Int8
            Unsigned
                UInt128
                UInt16
                UInt32
                UInt64
                UInt8
        Rational

User-defined and composite data types


可自訂資料型別: use abstract|primitive type, struct, mutable struct for type definitions


ref: crazy idea: change the type keyword


julia> struct Person
           name::String
           age::Int64
       end

julia> typeof(Person)
DataType

julia> a = Person("Name", 10)
Person("Name", 10)

julia> typeof(a)
Person

julia> a.name
"Name"

julia> a.name = "name2"
ERROR: type Person is immutable

檢查自訂資料型別的層級


julia> supertype(Person)
Any

julia> subtypes(Person)
0-element Array{Type,1}

julia> fieldnames(Person)
(:name, :age)

julia> typeof(:name)
Symbol



composite types

剛剛的 Person 資料無法修改,使用 mutable struct 就可以變成可修改的資料型別


julia> mutable struct Point
           x :: Int64
           y :: Int64
           z :: Int64
       end

julia> p = Point(1,2,3)
Point(1, 2, 3)

julia> p.x=10
10

julia> p
Point(10, 2, 3)

Inner constructor


剛剛的 struct,可在 constructor 中,增加資料的檢查,確認新的物件符合資料型別設計的條件


julia> struct Family
          num_members :: Int64
          members :: Array{String, 1}

          # inner constructor in play
          Family(num_members, members) = num_members != length(members) ? error("Mismatch!!") : new(num_members, members)
       end

julia> f1 = Family(1, ["husband", "wife"])
ERROR: Mismatch!!
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] Family(::Int64, ::Array{String,1}) at ./REPL[14]:6
 [3] top-level scope at none:0

julia> f2 = Family(2, ["husband", "wife"])
Family(2, ["husband", "wife"])

Modules and interfaces


julia 的 namespaces,可讓我們建立 top-level global variable,但又不會在所有程式中互相衝突。


module SampleModule
..
..
end

julia> module MyModule
                  foo=10
                  bar=20
                  function baz()
                      "baz"
                  end
                  function qux()
                      "qux"
                  end
                  export foo, baz
                  end
Main.MyModule

julia> MyModule.bar
20

using MyModule 跟 import MyModule 的差異


  • using MyModule,會將所有 exported functions 都帶入目前的 scope,等於是宣告 MyModule.foo,可以這樣使用 MyModule:foo
  • import MyModule,將 functions 匯入目前的 scope,只能取得 exported functions/variables,就無法使用 foo



Including files in modules

當 module, package 分散在多個檔案中,使用 include 彙整


# 按下 ; 進入 shell
# transformations.jl 是獨立的檔案
shell> cat transformations.jl
function say_hello(name:: String)
    "hello, $name"
end
julia> include("transformations.jl")
say_hello (generic function with 1 method)

julia> say_hello("rahul")
"hello, rahul"

Module file paths


通常用 using SomeModule 時,julia 會尋找預設 module 路徑


可用 push! 增加 library 路徑,或是設定環境變數 JULIA_LOAD_PATH


julia> push!(LOAD_PATH, "~/Downloads/Module/")
4-element Array{String,1}:
 "@"
 "@v#.#"
 "@stdlib"
 "~/Downloads/Module/"



module precompilation

在使用某個 module 時,會先花一些時間進行編譯,如果有編譯完成的,才會直接匯入


目前 1.0 版,所有 modules 都是enable precompilation


Samplecode.jl


module Samplecode

export sum_of_numbers

sum_of_numbers = 0
for num in 1:10000
    global sum_of_numbers += num
end

end

julia> push!(LOAD_PATH, "~/path/")
4-element Array{String,1}:
 "@"
 "@v#.#"
 "@stdlib"
 "~/path/"

julia> @time using Samplecode
[ Info: Precompiling Samplecode [top-level]
  1.343508 seconds (1.13 M allocations: 55.605 MiB, 0.38% gc time)

julia> @time using Samplecode
  0.000552 seconds (782 allocations: 42.547 KiB)

multiple dispatch


julia> struct Coordinate{T}
                  x::T
                  y::T
                  z::T
              end

julia> function calc_sum(value::Coordinate{Int64})
                  value.x + value.y + value.z
              end
calc_sum (generic function with 1 method)

julia> function calc_sum(value::Coordinate{Float64})
                         value.x + value.y + value.z
              end
calc_sum (generic function with 2 methods)

julia> methods(calc_sum)
# 2 methods for generic function "calc_sum":
[1] calc_sum(value::Coordinate{Float64}) in Main at REPL[6]:2
[2] calc_sum(value::Coordinate{Int64}) in Main at REPL[5]:2

julia> calc_sum(Coordinate(1,2,3))
6

julia> calc_sum(Coordinate(1.0,2.0,3.0))
6.0

References


Learning Julia

2019/5/13

Functions in Julia


Creating Functions


function 的定義:an object that maps a tuple of arguments values to a return value


julia> function greet()
           println("hello world")
       end
greet (generic function with 1 method)

julia> greet()
hello world
        
julia> function calculator(x, y, operation)
           if operation == "+"
               x+y
           elseif operation == "-"
               x-y
           elseif operation == "*"
               x*y
           elseif operation == "/"
               x/y
           else
               println("Incorrect operation")
               return 0
           end
       end
calculator (generic function with 1 method)

julia> println(calculator(10,20, "+"))
30

julia> println(calculator(10,20, "*"))
200



如果在 function 名稱最後面看到 ! 這個符號,這是 julia 的命名習慣,這表示這個 function 會修改 input 的參數資料內容,例如 push!


julia> push!([1,2,3], 4)
4-element Array{Int64,1}:
 1
 2
 3
 4

Function Argurments


通常參數是以 pass by value 或是 pass by reference 的方式處理,但 julia 是使用 pass by sharing 的方式。


pass by value: 傳入 function 的參數,會複製數值,這表示該變數會產生 2 copies


pass by reference: function 的參數,會使用該變數的 reference,該變數只有 1 copy


pass by sharing: 傳入 function 的變數,不會被複製。參數本身只是一個新的 binding,參考到原本變數的值。這也很像是 pass by value,只是那個 value 是 object reference。


ref: 深入探討 JavaScript 中的參數傳遞:call by value 還是 reference?


以 function 內對參數重新賦值,外面的變數如果也會改變,就是 pass by reference。如果不會改變就是 pass by value,在 pass by value 的條件下,如果可以透過變數,修改 function 外面的變數的值,就是 pass by sharing。




return keyword

return 用來結束 function 執行,julia 的 function 可使用或不使用 return,如果 function 沒有 return,就表示會回傳最後一個 statement 的運算結果。


julia> function add_without_return(x,y)
               x+y
       end
add_without_return (generic function with 1 method)

julia> function add_using_return(x,y)
               return x+y
       end
add_using_return (generic function with 1 method)

julia> add_without_return(20,30) == add_using_return(20,30)
true



arguments

傳入的參數,可以不指定資料型別,也可以限制資料型別。限制資料型別,可讓 compiler 介入並最佳化編譯結果。


function say_hello(name)
    println("hello $name")
end
say_hello("world")

function say_hello(name::String)
    println("hello $name")
end
say_hello("world")

function 可以沒有任何參數


julia> function does_nothing
       end
does_nothing (generic function with 0 methods)

varargs 是 variable arguments,不定長度的參數,julia 是使用 ...


傳入三個參數,第一個獨立,第2,3 個參數,在 function 裡面是對應為 y...,所以 y 是 tuple


julia> function letsplay(x,y...)
           println(x)
           println(y)
       end
letsplay (generic function with 1 method)

julia> letsplay("cricket","hockey","tennis")
cricket
("hockey", "tennis")



傳入 function 的變數,可以在定義 function 前,就先宣告該變數



x = (1,2,3,4,5)
y = (6,7,8)

function numbers(a...)
    println("the arguments x are -> ", x)
    println("the arguments a are -> ", a)
end

numbers(y)
# the arguments x are -> (1, 2, 3, 4, 5)
# the arguments a are -> ((6, 7, 8),)

x = [1,2,3,4,5]
y = [6,7,8]

numbers(y)
# the arguments x are -> [1, 2, 3, 4, 5]
# the arguments a are -> ([6, 7, 8],)



optional arguments

function 中有些參數已經有預設值,呼叫該 function 就不需要傳入該參數


function f(x, y=4, z=10)
    x+y+z
end

f(10)
# 24



variable scope

julia 有兩個主要的 scope: global, local


module 內或是 REPL 內的變數,通常是 global scope。loops, functions, macros, try-catch-finally block 裡面的變數是 local scope。


如果刻意加上 global,可讓變數變成 global scope


julia> for i=1:5
               global hello
               hello = i
       end

julia> hello
5



lexical scoping: funtion 的 scope 不會繼承 caller's scope,而是由 function 定義的時候開始。例如 module 內定義了 name 變數,後面又定義了另一個 name,當呼叫 module 內的 method,使用的 name 變數,是一開始在 module 內定義的 name。


julia> module Utility
               name = "Julia"
               tell_name() = name
       end
Main.Utility

julia> name = "Python"
"Python"

julia> Utility.tell_name()
"Julia"



julia 將 local scope 分為 soft 及 hard local scope,function 裡面是 hard local scope。




nested functions

* 如果是兩個整數,就是整數相加,如果是兩個字串,則是將字串連接在一起


julia> function outer(value_a)
               function inner(value_b)
                       return value_a * value_b
               end
       end
outer (generic function with 1 method)

# 回傳一個 function
julia> result = outer(10)
(::getfield(Main, Symbol("#inner#3")){Int64}) (generic function with 1 method)

julia> typeof(result)
getfield(Main, Symbol("#inner#3")){Int64}

julia> result(10)
100

julia> result = outer("learning ")
(::getfield(Main, Symbol("#inner#3")){String}) (generic function with 1 method)

julia> result("Julia")
"learning Julia"

Anonymous Functions


也可稱為 lambda functions


語法:f -> 2f


map() 的第一個參數,需要傳入一個 function,可使用 anonymous function


julia> map(f -> 2f, [2, 3])
2-element Array{Int64,1}:
 4
 6

julia> map(f -> 2f, [2 3])
1×2 Array{Int64,2}:
 4  6

julia> map((f,g) -> 2f + 2g, [2,3], [3,4])
2-element Array{Int64,1}:
 10
 14

Multiple Dispatch


dispatch 就是 to send 的意思,也就是 send a message to a listener,或是 call to a function


dispatch 有以下形式


  • static dispatch


    在 compile time 定義 dispatch order,在執行程式前,就已經知道所有資料型別。compiler 能夠對所有可能的資料型別的組合,都產生對應的程式碼,並預先知道什麼時候在哪裡被使用。這是程式語言中最常見的形式。


    可用 funct() 或是 x.functiont() 呼叫 function / method,每次呼叫時都是固定不變的。

  • dynamic dispatch


    runtime 定義 dispatch order。compiler 會產生所有 functions 的 lookup table,在 runtime 決定要呼叫哪一個 function。


    例如有 classA, classB 都有 foo() function,runtime 時,兩個 class 都會被檢查到有 foo(),可能或呼叫 classA.foo() 或是 classB.foo() 任一個 function

  • multiple dispatch


    dispatch order 跟 function name 以及 argument types 有關,runtime 決定使用的 signature of the function 以及 actual implementation。


    classA 有 foo(int) 以及 foo(char) ,當呼叫 classA.foo(x) 時,在 runtime 會檢查 classA 及 x,然後決定要使用哪一個 function


julia 使用 multiple dispatch




Understanding methods

尋找適當的函數,同時會檢查參數的資料型別


function add_numbers(num1::Int64, num2::Int64)
    return num1 + num2
end

add_numbers(10,20)

add_numbers(10.0,20.0)
# ERROR: MethodError: no method matching add_numbers(::Float64, ::Float64)

function add_numbers(num1::Float64, num2::Float64)
    return num1+num2
end

julia> methods(add_numbers)
# 2 methods for generic function "add_numbers":
[1] add_numbers(num1::Float64, num2::Float64) in Main at REPL[36]:2
[2] add_numbers(num1::Int64, num2::Int64) in Main at REPL[33]:2

如果要用一個 methd 同時支援多種資料型別,可以用類似 python 的做法,不指定參數的資料型別


function add_without_types(num1,num2)
    return num1+num2
end

add_without_types(10.0,20)

add_without_types(10,20.0)

Recursion


遞迴: 重複呼叫自己的 function


function generate_fibonacci(n::Int64)
    if n < 2
        return 1
    else
        return generate_fibonacci(n-1) + generate_fibonacci(n-2)
    end
end

# 另一種更簡單的寫法
generate_fibonacci(n) = n < 2 ? n : generate_fibonacci(n - 1) + generate_fibonacci(n - 2)

Built-in Functions


julia 的 base library 提供很多內建的 functions


  • workspace()


    只能在 REPL 使用,可以將目前 REPL 的所有資料清空


    note: 這個function 在 julia 1.0 已經不提供了


    ref: https://stackoverflow.com/questions/51872039/which-is-the-alternative-to-workspace-in-julia-1-0

  • typeof()


    查詢參數的資料型別

  • methods()


    查詢所有提供該 method 的 functions


    julia> methods(+)
    # 163 methods for generic function "+":
    [1] +(x::Bool, z::Complex{Bool}) in Base at complex.jl:277
    [2] +(x::Bool, y::Bool) in Base at bool.jl:104
    ...
  • readline(), readlines()


    由 STDIN 讀取 user input,如果加上參數,則是自檔案讀取資料


    julia> name = readline()
    julia
    "julia"
    
    julia> readlines("file.txt")
    43-element Array{String,1}:
    ...
  • enumerate()


    用來 iterate over a collection


    julia> fruits = ["apple", "orange", "banana"]
    3-element Array{String,1}:
     "apple"
     "orange"
     "banana"
    
    julia> for (index,fruit) in enumerate(fruits)
                   println("$index -> $fruit")
           end
    1 -> apple
    2 -> orange
    3 -> banana
  • parse()


    用來 parse a string,轉換為 number parse(type, str; base) base 是代表幾進位


    julia> parse(Int, "2")
    2
    
    julia> parse(Float64, "2.2")
    2.2
    
    julia> parse(Int, "1234", base = 5)
    194

References


Learning Julia

2019/5/6

Programming Concepts in Julia


julia 提供很多讓 data scientists , statisticians 使用的功能,也非常接近 MATLAB, Python, R 的語法。


Revisiting programming paradigms


有四種:


  1. Imperative: C


    sequential execution,可改變變數的值。是以 Von Neumann computer 概念發展的,有 reusable memory,可修改 state。


    優點:


    • 有效利用系統資源
    • 接近 machine language

    缺點:


    • 有些問題無法單純以遵循 order of statements 解決
    • 因為可修改 state,讓程式比較難被理解
    • debug 不直覺
    • 只能完成有限的抽象化
  2. Logical: Prolog


    也稱為 rule-based paradigm,程式會處理資料,建立 rules 的組合,提供 logical expression。沒有 function,以 relations 取代。 Y=f(x) 改為 r(X, Y)


    ex:


    male(X) // X is a male
    father(F,X) // F is father of X
    father(F,Y) // F is father of Y
    mother(M,X) // M is mother of X
    mother(M,Y) // M is mother of Y
    
    // The preceding relationship implies:
    brother(X,Y) // X is a brother of Y
  3. Functional: Haskell


    由數學概念發展而來,將所有subprogram 都視為 functions。function 可當參數,也可以回傳 function。可將 imperative paradigm 轉換為 functional paradigm。


    優點:


    • function 為高階抽象概念,減少錯誤。
    • 適合用在 parallel computation
    • value 為 non-mutable

    缺點:


    • 在需要很多 sequential activity 的狀況下會很複雜。使用 imperative / object-oriented 會比較洽當。
    • 程式可能會比較沒有效率
  4. Object-oriented: Smalltalk


    everythin is an object,可利用 behavior/method 修改物件的狀態 state


    有四個基本概念:


    • encapsulation
    • abstration
    • inheritance
    • polymorphism

Starting with Julia REPL


julia REPL 可直接執行 statements


$ julia -e 'println("HelloWorld")'
HelloWorld

$ julia -e 'for i=1:5; println("HelloWorld"); end'
HelloWorld
HelloWorld
HelloWorld
HelloWorld
HelloWorld

$ julia -e 'for i in ARGS; println(i); end' test1 test2 test3
test1
test2
test3

ARGS 可以取得 command line 參數


Variables


swap 變數


julia> x=24
24

julia> y=10
10

julia> x,y=y,x
(10, 24)

julia> x
10

可使用 unicode 變數名稱,或是以 _ 開頭


julia> 測試=100
100

julia> 測試
100

julia> _ab=40
40

pi 是內建的常數,不要用在自訂變數名稱


julia> pi
π = 3.1415926535897...

Naming Conventions


  • 通常變數名稱是小寫字母
  • 可使用 _ 但不建議使用
  • Function 及 macro 名稱是小寫字母
  • module 與 type 的第一個字母為大寫,名稱中不同的字,字首大寫: Upper Camel Case
  • 會修改/改寫參數(輸入資料)的 function,以 ! 結尾

a = Int64[]
push!(a, 1)    # => [1]
push!(a, 2)    # => [1,2]
push!(a, 3)    # => [1,2,3]
pop!(a)  # => 3
a # => [1,2]

可使用 typeof() 查詢變數的資料型別


julia> typeof(a)
Array{Int64,1}

numbers 可以用 _ 增加可讀性


julia> 100_000_000
100000000

julia> 1_0_0
100

Integers, bits, bytes, and bools


primitive numeric types


Type number of bits smallest values largest value
Int8 8 -2^7 2^7-1
UInt8 8 0 2^8-1
Int16 16 -2^15 2^15-1
UInt16 16 0 2^16-1
Int32 32 -2^31 2^31-1
UInt32 32 0 2^32-1
Int64 64 -2^63 2^63-1
UInt64 64 0 2^64-1
Int128 128 -2^127 2^127-1
UInt128 128 0 2^128-1
Bool 8 false(0) true(1)

可用 typemax, typemin 取得最大/最小值


julia> typemax(Int32)
2147483647

julia> typemin(Int32)
-2147483648

在 64bits 機器,數字預設型別為 Int64,也可用 Sys.WORD_SIZE (word size) 檢查機器的位元數


julia> typeof(10)
Int64
julia> Sys.WORD_SIZE
64



因為 julia 是 strong-type language,變數會維持原本的資料型別,在發生 overflowing 時,可能會取得錯誤的答案


julia> x = Int16(10000)
10000

julia> println(x*x)
-7936

julia> x=typemax(Int16)
32767

julia> x+Int16(1)
-32768



Bool 可用 true/false 為值, 0, NULL, empty string 不能視為 false


julia> 1>2
false

julia> typeof(ans)
Bool

julia> if 0
       println("hello")
       end
ERROR: TypeError: non-boolean (Int64) used in boolean context
Stacktrace:
 [1] top-level scope at none:0

Floating point number in Julia


type precision number of bits
Float16 half 16
Float32 single 32
Float64 double 64

julia> 100.0
100.0

julia> 24.
24.0

julia> .1
0.1

julia> typeof(ans)
Float64

julia> 0 == -0
true

julia> bitstring(0)
"0000000000000000000000000000000000000000000000000000000000000000"

julia> bitstring(-0)
"0000000000000000000000000000000000000000000000000000000000000000"

可使用 exponenital notation


julia> 2.99e8
2.99e8

julia> 2.99e8 > 99999
true

julia> 2.99f8
2.99f8

julia> 2.99e8 == 2.99f8
true

julia> typeof(2.99e8)
Float64

julia> typeof(2.99f8)
Float32

也可以使用 hexadecimal floating point literals,但只有 Float64


julia> 0x4.1p1
8.125

julia> typeof(ans)
Float64



Inf, -Inf, NaN


julia> 1/0
Inf

julia> -1/0
-Inf

julia> 0/0
NaN

julia> Inf/Inf
NaN

下(前)一個可以表示的 floating point number: nextfloat(), prevfloat()


julia> nextfloat(0.0)
5.0e-324

julia> prevfloat(0.0)
-5.0e-324



有時會遇到,計算結果跟預期的不同,這是因為該數字無法以正確的 floating-point representation 表示,就必須 rounded 到適當的 value。預設是 RoundNearest


julia> 0.1+0.2
0.30000000000000004
julia> 1.1+0.1
1.2000000000000002

這是因為 computer 無法正確表示 0.1, 0.2, 0.3 這樣的數字


ref: Strange behaviour when adding floating numbers


ref: What Every Programmer Should Know About Floating-Point Arithmetic




BigInt, BigFloat


julia 提供了不同精確度的計算方法。他使用了 GNU Multiple Precision Arithmetic Library, GMPGNU MPFR Library,並使用 BigInt, BigFloat 提供任意精確度的整數及浮點數。


julia> setrounding(BigFloat, RoundUp) do
                  BigFloat(1) + parse(BigFloat, "0.1")
              end
1.100000000000000000000000000000000000000000000000000000000000000000000000000003

julia> setrounding(BigFloat, RoundDown) do
                  BigFloat(1) + parse(BigFloat, "0.1")
              end
1.099999999999999999999999999999999999999999999999999999999999999999999999999986

julia> setprecision(40) do
                  BigFloat(1) + parse(BigFloat, "0.1")
              end
1.1000000000004



在寫數學方程式時,不需要特定寫 *


julia> x=4;y=5
5

julia> 3x+4y+5
37

Logical and arithmetic operations


+, -, *, /, ^, !, and %


julia> a=20;b=10
10

julia> a+b
30

julia> -a
-20

julia> !(4>2)
false

julia> -(-a)
20



bitwise operations


expression name
~x bitwise not
x & y bitwise and
x | y bitwise or
x ⊻ y bitwise xor
x >>> y logical shift right
x >> y arithmetic shift right
x << y logical/arithmetic shift left



+=, -=, *=, /=


julia> x=4
4

julia> x+=10
14

julia> x/=2
7.0

==, !=, <, <=, >, >=


julia> 100 > 99.99
true

julia> 24 == 24.0
true

julia> 24 === 24.0
false

julia> 24 !== 24.0
true

julia> NaN == NaN
false

julia> NaN === NaN
true

julia> Inf == Inf
true

julia> Inf >= NaN
false

可以 chain together


julia> 10 > 20 < 30 >= 30.0 == 100 > 101
false



precendence of operators 的執行順序


  1. Syntax (. followed by ::)
  2. Exponentiation (^)
  3. Fractions (//)
  4. Multiplication (*, /, %, &, and )
  5. Bitshifts (<<, >>, and >>>)
  6. Addition (+, -, |, and $)
  7. Syntax (:, .., and |>)
  8. Comparisons (>, <, >=, <=, ==, ===, !=, !==, and <:)
  9. Control flow (&& followed by || followed by ?)
  10. Assignments (=, +=, -=, *=, /=, //=, =, ^=, ÷=, %=, |=, &=, $=, <<=, >>=, and >>>=)



型別轉換


julia> Int8(100)
100

julia> Int8(100*10)
ERROR: InexactError: trunc(Int8, 1000)
Stacktrace:
 [1] throw_inexacterror(::Symbol, ::Any, ::Int64) at ./boot.jl:567
 [2] checked_trunc_sint at ./boot.jl:589 [inlined]
 [3] toInt8 at ./boot.jl:604 [inlined]
 [4] Int8(::Int64) at ./boot.jl:714
 [5] top-level scope at none:0

julia> Int16(100*10)
1000

Arrays and matrices


array 的 index 以 1 開始,不是 0。另外 array 的所有資料的型別都會是一樣的。


julia> a=[1,2,3,4]
4-element Array{Int64,1}:
 1
 2
 3
 4

julia> a[2]
2

julia> a[2:4]
3-element Array{Int64,1}:
 2
 3
 4

julia> ra=rand(1:10, 6)
6-element Array{Int64,1}:
  5
  2
  6
 10
  1
  5

julia> b=[1,2,2.5]
3-element Array{Float64,1}:
 1.0
 2.0
 2.5



List Comprehension in Julia


julia> pow2 = Array{Int64}(undef, 10)
10-element Array{Int64,1}:
 4634856432
 4634856352
          1
 4634856512
 4634856592
 4634856672
          8
          4
          2
          1

julia> pow2[1] = 2
2

julia> [pow2[i] = 2^i for i = 2:length(pow2)]; pow2
10-element Array{Int64,1}:
    2
    4
    8
   16
   32
   64
  128
  256
  512
 1024

建立空白沒有任何元素的 array


julia> empty_array = Float64[]
0-element Array{Float64,1}

julia> println(empty_array)
Float64[]

julia> push!(empty_array,1.1)
1-element Array{Float64,1}:
 1.1

julia> push!(empty_array,2.2,3.3)
3-element Array{Float64,1}:
 1.1
 2.2
 3.3

julia> append!(empty_array,[101.1,202.2,303.3])
6-element Array{Float64,1}:
   1.1
   2.2
   3.3
 101.1
 202.2
 303.3

產生 4x1 matrix


julia> X = Array{Int64}(undef, 4,1)
4×1 Array{Int64,2}:
 4371931344
 4367076560
 4496885520
 4405372192

julia> fill!(X,4)
4×1 Array{Int64,2}:
 4
 4
 4
 4

julia> X[2] = 10; X
4×1 Array{Int64,2}:
  4
 10
  4
  4



矩陣


# 產生 3x2 矩陣
julia> A = [2 4; 8 16; 32 64]
3×2 Array{Int64,2}:
  2   4
  8  16
 32  64

# reshape 可轉換為轉置矩陣 2x3
julia> println(reshape(A,2,3))
[2 32 16; 8 4 64]

julia> println(reshape(A,1,6))
[2 8 32 4 16 64]

# transpose 也是轉置矩陣
julia> transpose(A)
2×3 LinearAlgebra.Transpose{Int64,Array{Int64,2}}:
 2   8  32
 4  16  64

矩陣的加法跟乘法


julia> B = [1 1 2; 3 5 8]
2×3 Array{Int64,2}:
 1  1  2
 3  5  8

julia> transpose(A)+B
2×3 Array{Int64,2}:
 3   9  34
 7  21  72

julia> transpose(A)*transpose(B)
2×2 Array{Int64,2}:
  74  302
 148  604

有一種特別的矩陣乘法 .*,就是將各對應元素相乘,而不是標準的矩陣乘法


julia> transpose(A).*B
2×3 Array{Int64,2}:
  2   8   64
 12  80  512

julia> transpose(A) .== B
2×3 BitArray{2}:
 false  false  false
 false  false  false



rand 可產生亂數矩陣


julia> multiA = rand(3,3,3)
3×3×3 Array{Float64,3}:



sparse matrix 稀疏矩陣: 矩陣內大部分的元素都是0


julia> using SparseArrays

julia> sm = spzeros(5,5)
5×5 SparseMatrixCSC{Float64,Int64} with 0 stored entries

julia> sm[1,1] = 10
10

julia> sm
5×5 SparseMatrixCSC{Float64,Int64} with 1 stored entry:
  [1, 1]  =  10.0

Understanding DataFrames


DataFrame 是有 labeled columns 的 data structure,很像是 SQL table/spreadsheet,2 dimensions,可視為 a list of dictionaries


DataFrames.jl 這個 package 處理,建議用在 statistical analysis


在新版 julia 1.0 以後,DataArray 不能使用了 改用 missing 代表 missing value


# 首先必須要先知道 array,可能會有兩種資料型別,要事先定義
julia> x = Union{Missing, String}["a", "b"]
2-element Array{Union{Missing, String},1}:
 "a"
 "b"

# 就可以將某個元素設定為 missing
julia> x[1] = missing
missing

julia> x
2-element Array{Union{Missing, String},1}:
 missing
 "b"



julia> Pkg.add("DataFrames")

julia> using DataFrames

julia> df = DataFrame(Name = ["Julia", "Python"], Version = [0.5, 3.6])
2×2 DataFrame
│ Row │ Name   │ Version │
│     │ String │ Float64 │
├─────┼────────┼─────────┤
│ 1   │ Julia  │ 0.5     │
│ 2   │ Python │ 3.6     │

References


Learning Julia