Julia の Dataframes の列名で、正規表現が使えるRの "grep" をする方法
julia には、R の grep と同じ働きをするコマンドはありません。
結論の定義を書きます。ブロードキャスト "." というのを使って、contains.(), または、ismatch.() して、true を、find() で探せば良いです。"set" を、iris という Dataframe の :Species という列 (column) から探します。
または、find(contains.(iris[:Species] , "set"))
find(ismatch.(r"set" , iris[:Species]))
恐らく、これが関数を使った記載で、回帰的に書かない、シンプルな記載ではないかと考えます。r" " というのは、正規表現のマクロだそうです。contain() か、ismatch() の使い方と、find() の組合せなので、下記より覚えやすいと思います。
以下は、昔、がんばって書いた分です。参考になる人がいたら幸いです。Dataframes の列名で、grep する関数を定義しました。
function grep(word, array) foo = find(ismatch(Regex(word), x) for x in array) return foo end
注
- word には、"" で、単語の一部などを入れて下さい。array は、下記の iris の例なら iris[:Species] を入れます。順番は、R の grep の順にしました。
- 正規表現で探したい場合は、word の部分を r"" で入力して下さい。例えば、Regex(r"hoge$") は、r"hoge$" を返しので動くはずです。
- [ismatch(Regex(word), x) for x in array] だけなら、true or false の Bool で返ります。これを find() の中に入れると、true のある番号を返してくれます。Bool の方が良ければ、foo = [ismatch(Regex(word), x) for x in array] と書けば良いでしょう。
- Regex(word) で、word に代入した文字列が正規表現化されます。
- 正規表現が必要なければ、foo = find(contains(x, word) for x in array) でも同じ結果になります。
上記で定義した grep 関数の実例は最後に書いてあります。毎度、おなじみの R のデータセット iris を例に、順をおって勉強してみましょう。
using RDatasets
iris = dataset("datasets", "iris")
これで、iris に格納されるはずです。
という、3つの種のデータが50個ずつですね。julia> by(iris, :Species, nrow) 3×2 DataFrames.DataFrame │ Row │ Species │ x1 │ ├─────┼──────────────┼────┤ │ 1 │ "setosa" │ 50 │ │ 2 │ "versicolor" │ 50 │ │ 3 │ "virginica" │ 50 │
このうち、"set" で含むものを採ってきましょう。まずは、正規表現の関係がない contains() を使ってみます。
[contains(x,"set") for x in iris[:Species]]
と書けば Bool で返ります。 "setosa" のところが、true になっているはずです。
次に、R の grep() は、行番号を返すので、true のところの番号を返す find() を使います。
iris[ find( contains(x,"set") for x in iris[:Species] ) , :]または、
iris[find( x->contains(x,"set"),iris[:Species] ), :]とします。
含まないものは、"!" を "contains" の前に付けて、
find( !contains(x,"set") for x in iris[:Species] )または、
find( x->!contains(x,"set"),iris[:Species] )
と書けば良いです。
しかし、find( x->!contains(x,"set"),iris[:Species] ) は、正規表現がたぶん使えません。
正規表現を使いたい派のあなたと、ブリーアン型のベクトルを作って複数の条件を組み合わせたいあなたは、ismatch を使いましょう。
[ismatch(r"set", x ) for x in iris[:Species] ]これで true or false で返してくれます。r""というのは、マクロらしいです。Regex() の中に入れても同じ動きをします。残念ながら、ismatch() は、正規表現に変換しないと動かないようです。再帰的な記載をしましたが、for ループで積み上げる記載だと下記のようになります。
foo=[]
foo=ismatch(r"set",iris[1,:Species] )
for i in 2:size(iris)[1]
foo=[foo; ismatch(r"set",iris[i,:Species] ) ]
end
参考までに正規表現では、始まりの検索は、r("^set") 、終りの検索は、r("set$") と書けば良いのです。(今回の例では、r("set$") は、全部 false になります。)
この Bool に対して、find() で、true の番号を返せば、R の grep() に相当する機能になるわけです。
では、はじめに定義した grep() の用法例です。
julia> iris[grep("set", iris[:Species]),:] 50×5 DataFrames.DataFrame │ Row │ SepalLength │ SepalWidth │ PetalLength │ PetalWidth │ Species │ ├─────┼─────────────┼────────────┼─────────────┼────────────┼──────────┤ │ 1 │ 5.1 │ 3.5 │ 1.4 │ 0.2 │ "setosa" │ │ 2 │ 4.9 │ 3.0 │ 1.4 │ 0.2 │ "setosa" │ │ 3 │ 4.7 │ 3.2 │ 1.3 │ 0.2 │ "setosa" │ │ 4 │ 4.6 │ 3.1 │ 1.5 │ 0.2 │ "setosa" │ │ 5 │ 5.0 │ 3.6 │ 1.4 │ 0.2 │ "setosa" │ │ 6 │ 5.4 │ 3.9 │ 1.7 │ 0.4 │ "setosa" │ │ 7 │ 4.6 │ 3.4 │ 1.4 │ 0.3 │ "setosa" │ │ 8 │ 5.0 │ 3.4 │ 1.5 │ 0.2 │ "setosa" │ │ 9 │ 4.4 │ 2.9 │ 1.4 │ 0.2 │ "setosa" │ ⋮ │ 41 │ 5.0 │ 3.5 │ 1.3 │ 0.3 │ "setosa" │ │ 42 │ 4.5 │ 2.3 │ 1.3 │ 0.3 │ "setosa" │ │ 43 │ 4.4 │ 3.2 │ 1.3 │ 0.2 │ "setosa" │ │ 44 │ 5.0 │ 3.5 │ 1.6 │ 0.6 │ "setosa" │ │ 45 │ 5.1 │ 3.8 │ 1.9 │ 0.4 │ "setosa" │ │ 46 │ 4.8 │ 3.0 │ 1.4 │ 0.3 │ "setosa" │ │ 47 │ 5.1 │ 3.8 │ 1.6 │ 0.2 │ "setosa" │ │ 48 │ 4.6 │ 3.2 │ 1.4 │ 0.2 │ "setosa" │ │ 49 │ 5.3 │ 3.7 │ 1.5 │ 0.2 │ "setosa" │ │ 50 │ 5.0 │ 3.3 │ 1.4 │ 0.2 │ "setosa" │
以上、R の grep 相当の動きをするはずです。