Open11

Juliaでデータ加工いろいろ

Y8Y8

Base.jl

findall()を使った配列の抽出方法

item_set = ["a", "b", "c"]
prob_set = [0.1, 0.2, 0.7]

prob_set[findall(==("a"), item_set)] .*= 2

println(prob_set)
#> [0.2, 0.2, 0.7]
Y8Y8

juliaのfind関数を整理

  • argmin() / argmax()は値が最も小さい/大きい場所のインデックスを返す.
  • findmin() / findmax()は小さい値とインデックスを返す
  • extrema()は最も小さい値と大きい値を返すので、rのrange()関数と同じ
  • findfirst() / findlast()は条件を満たす最初の/最後のインデックスを返す
  • findall()は条件を満たすすべてのインデックスを返す
  • findnext()は検索開始位置を指定して、そのあとに条件を満たすインデックスを返す
  • findprev()はfindnext()の反対
x = [3, 7, 4, 5, 10, 3, 12, 3, 2, 4]
println(argmin(x))
#> 9 # return index
println(findmin(x))
#> (2, 9) # return value and index: tuple
println(extrema(x))
#> (2, 12) #return values (min, max): tuple
println(findfirst(x .== 3))
#> 1 # return index
println(findall(x .== 3))
#> [1, 6, 8]

x = [1, 1, 1, 3, 4]
println(findnext(x .== 1, 2))
#> 2 # return index

配列に対しても可能

x = [1 2 3; 3 5 6]
argmax(x)
#> CartesianIndex(2, 3)
findmin(x)
#> (1, CartesianIndex(1, 1))
findall(x .== 3)
#> 2-element Vector{CartesianIndex{2}}:
#>  CartesianIndex(2, 1)
#>  CartesianIndex(1, 3)

findnext()関数を配列に対して使うと注意が必要?
6から検索開始して、得られたのは、(3,3)なので、
一方向にしか検索しないのではないか

x = [1 2 3; 
    3 5 6; 
    3 8 3]
findnext(x .== 3, CartesianIndex(2, 3))
#> CartesianIndex(3, 3)

x = [1 2 4; 
    3 5 3; 
    3 8 3]
findnext(x .== 3, CartesianIndex(1, 3))
#> CartesianIndex(2, 3)

参考サイト)

Y8Y8

.を使った書き方はブロードキャストを使った書き方なので、それをしない場合は下記のように

a = [2, 1, 3]
findall(x->x==minimum(a), a)
#> 1-element Vector{Int64}:
#> 2
Y8Y8
a = [2, 1, 3]
findall(==(minimum(a)), a)
#> 1-element Vector{Int64}:
#> 2

のようにも書ける

findall(==minimum(a), a)のように書くと、下記のようなエラーがでてしまう

syntax: "==" is not a unary operator

文字列に対しても

item_set = ["a", "b", "c"]
findall(==("b"), item_set)
#> 1-element Vector{Int64}:
#> 2

のように書くことでシンプルに書くことができる

findall(isequal("b"), item_set)

とすると、さらにわかりやすい

Y8Y8

mutate(col = case_when(a == 1 ~ 0, TRUE ~ 1))をjuliaで書く方法

シンプルな ifelse() チェーン

d_sample = DataFrame(
    a = 1:3,
    b = 2:4,
    c = ["a", "b", "c"]
)

d_sample.a = ifelse.(
    (d_sample.c .== "a") .& (d_sample.b .== 2), 5, d_sample.a
)

複雑なら関数に切り出して .() で各行に適用


  • DataFramesMeta.jlの@rtransform or @transform で行う
using DataFramesMeta
d_sample = DataFrame(
    a = 1:3,
    b = 2:4,
    c = ["a", "b", "c"]
)

d_sample = @chain d_sample begin
    @rtransform :d = ifelse(
        :c == "c" && :b == 4, 1,
        :c == "a" && :b == 2 ? 2 : 0
    )
end
Y8Y8

repeat()関数の使い方

repeat(1:3,  outer = 3)
#> 123123123

repeat(1:3,  inner = 3)
#> 111222333

repeat(1:3, outer = 2, inner = 2)
repeat(1:3, inner = 2, outer = 2)
#> 112233112233
  • outerは与えた配列を繰り返す
  • innerは与えた配列の要素をまず繰り返す
  • 両方与えたら、先にinnerを行う
Y8Y8

csvに出力する

using CSV
using DataFrames
df = DataFrame(
    a = [1,2],
    b = [2,3]
)

CSV.write("sample.csv", df, dlim = ",", writeheader = true)