裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

Re: dplyrでカラム名や値を変数で指定してもうまく認識されない

2022年03月28日 | Julia

dplyrでカラム名や値を変数で指定してもうまく認識されない
https://trunk28.com/dplyr_for/

引用元の記事は 2021/07/11 のものであるが,「dplyrでカラム名や値を変数で指定してもうまく認識されない」ということで,以下のプログラムはエラーになると...

library(dplyr)
hoge <- names(iris)[1]
iris %>% select(hoge)

エラー: Can't subset columns that don't exist.
x Column `hoge` doesn't exist.

しかし,R 4.2.0 では,以下の "Note" が出るが,一応正しい結果が得られる。

Note: Using an external vector in selections is ambiguous.
ℹ Use `all_of(hoge)` instead of `hoge` to silence this message.
ℹ See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
This message is displayed once per session.

解決法として以下のプログラムが提示されているが,.data[[hoge]] のようなわかりにくいものの説明をしている(.data というのは処理中のデータフレームの代名詞だとか)

追記 2022/03/30

中澤先生からのコメントがありました。ありがとうございます。

> hoge <- names(iris)[1]
> iris[,hoge] |> head()
[1] 5.1 4.9 4.7 4.6 5.0 5.4

R"""
library(dplyr)
hoge <- names(iris)[1]
iris %>% select(.data[[hoge]]) %>% head()
"""
RObject{VecSxp}
  Sepal.Length
1          5.1
2          4.9
3          4.7
4          4.6
5          5.0
6          5.4

しかも,select, group_by, summarise, relocate の場合は .data[[hoge]] でよいが,
mutate, transmute では mutate("{hoge2}":=Petal.Length+1) などとしなければならないなど,統一性がない。

正攻法は,警告メッセージにもあるが,all_of(hoge) を使うこと。これならまあ許せる。が,mutate, transmute ではこれも動かない。

R"""
library(dplyr)
hoge <- names(iris)[1]
iris %>% select(all_of(hoge)) %>% head()
"""

"Using an external vector in selections is ambiguous." ということだが,プログラム全体を見渡せば,hoge がカラム名でないことは明らかだと思うがなぁ。

Julia ではなんの問題もなく動く(当たり前だ)。

using DataFrames, RDatasets
iris = dataset("datasets", "iris");

hoge = names(iris)[1]
select(iris, hoge) |> x -> first(x, 5)

select() を使う必然性はまったくなく,iris[:, hoge] で十分。

コメント (2)
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Re: Juliaをもっと速くしよう!

2022年03月28日 | Julia

Juliaをもっと速くしよう!
https://zenn.dev/ohno/articles/0ba7970d419898

「多次元配列のメモリ上の位置は Julia, R, Fortran では(Python と違い)列優先なので,bad よりは,内側の for ループでは左側の添字を変化させる good のほうが速い」と書かれている。筆者は Windows のようであり,確かに good のほうが速いという結果が提示されている。

私の環境は Mac mini M1 チップなのだが,両者の違いは殆どなかった。

function bad(arr)
    sum = 0
    for i in 1:size(arr)[1]
        for j in 1:size(arr)[2]
           sum += arr[i,j]
        end
    end
    return sum
end

function good(arr)
    sum = 0
    for j in 1:size(arr)[2]
        for i in 1:size(arr)[1]
           sum += arr[i,j]
        end
    end
    return sum
end

実は,例に挙げられた関数はもっと早くなる。

sum = 0

sum = zero(eltype(arr))

にするだけだ。 sum = 0.0 でもよい。

「Julia は動的型付け言語じゃないか。sum = 0 のどこが悪い?」という人もいると思うが,

sum = 0 だと,sum は Union{Float64, Int64} になってしまう。

sum = zero(eltype(arr)) なら Float64 だ。

余計なことをしないで済むぶん,後者のほうが 6 倍ほど速い

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

PVアクセスランキング にほんブログ村

PVアクセスランキング にほんブログ村