注目の投稿

【kepler.gl】コロナ対策による人流の変化も地図上に可視化(各種メディアで報道)

kepler.glのサイト画面 kepler.glを使ってコロナ対策の効果を分析したところ、テレビ、新聞、ネットのメディアから問い合わせや報道依頼が殺到。今も、土日返上で都内や全国の人流変化を分析しています。この記事では人流変化の可視化に便利なkepler.glにつ...

ラベル 大規模データ の投稿を表示しています。 すべての投稿を表示
ラベル 大規模データ の投稿を表示しています。 すべての投稿を表示

2017年8月11日金曜日

R dplyrとはなんぞや?大規模データも簡単に処理? ~導入編~

dplyrとは

  1. Rで大規模データをさくさく処理するためのパッケージ
  2. 内部結合とかSQLみたいな処理もできる
  3. Rでデータ処理する人は必ず使ってる(くらいメジャーで有用)
以上!!

あとはだらだら使い方を説明。

使い方

まず、データを用意する。

用意するデータは、ドイツなどの株価指数のデータ。

(全然大規模データじゃないけど。。)

> #Rに最初からあるサンプルデータ(EuStockMarkets)を使う
> #中身は主要株価指数:DAX(ドイツ)、SMI(スイス)、CAC(フランス)、FTSE(イギリス)
> #データの先頭部分を確認してみる
> head(EuStockMarkets)
         DAX    SMI    CAC   FTSE
[1,] 1628.75 1678.1 1772.8 2443.6
[2,] 1613.63 1688.5 1750.5 2460.2
[3,] 1606.51 1678.6 1718.0 2448.2
[4,] 1621.04 1684.1 1708.1 2470.4
[5,] 1618.16 1686.6 1723.1 2484.7
[6,] 1610.61 1671.6 1714.3 2466.8
> #作図
> plot(EuStockMarkets)

plot(EuStockMarkets)の結果。上からドイツ、スイス、フランス、イギリスの主要株価指数の日次データ

グラフにすると分かりやすい♪

*このデータを使ったせいで後ほど不思議なエラーに遭遇します

準備①:dplyrをインストールする

下記のコードを実行。

> install.packages("dplyr")

これを実行すると、勝手にダウンロード・インストールが始まる。

インストールできたらdplyrを読み込む。

> library(dplyr)



準備②:データをtbl_dfというデータ構造に変換

(まあ、普通のデータフレーム:data.frameでも操作可能だけど。。)

ちなみに、dplyrを読み込まないと、、

> #tbl_df(データフレーム拡張したデータ構造)に変換
> EuStockMarkets_df <- tbl_df(EuStockMarkets)
Error in tbl_df(EuStockMarkets) : could not find function "tbl_df"

あ、エラーだ。
肝心のdplyr読み込むの忘れるとエラーになります。。

ちゃんと、dplyrを読み込むと、

> library(dplyr)

 次のパッケージを付け加えます: ‘dplyr’ 

 以下のオブジェクトは ‘package:data.table’ からマスクされています: 

     between, first, last 

 以下のオブジェクトは ‘package:stats’ からマスクされています: 

     filter, lag 

 以下のオブジェクトは ‘package:base’ からマスクされています: 

     intersect, setdiff, setequal, union 

> #tbl_df(データフレーム拡張したデータ構造)に変換
> EuStockMarkets_df <- tbl_df(EuStockMarkets)

エラーでません。

ちなみに、tbl_dfに変換しておくと、データ名実行でデータの要約が表示されます。

> EuStockMarkets_df
# A tibble: 1,860 x 4
       DAX    SMI    CAC   FTSE
     <dbl>  <dbl>  <dbl>  <dbl>
 1 1628.75 1678.1 1772.8 2443.6
 2 1613.63 1688.5 1750.5 2460.2
 3 1606.51 1678.6 1718.0 2448.2
 4 1621.04 1684.1 1708.1 2470.4
 5 1618.16 1686.6 1723.1 2484.7
 6 1610.61 1671.6 1714.3 2466.8
 7 1630.75 1682.9 1734.5 2487.9
 8 1640.17 1703.6 1757.4 2508.4
 9 1635.47 1697.5 1754.0 2510.5
10 1645.89 1716.3 1754.3 2497.4
# ... with 1,850 more rows

また、普通のデータフレームに変換して実行すると、

> data.frame(EuStockMarkets_df)

全データがコンソールに表示されます。
(今回は省いていますがコンソール画面はデータでいっぱいです)

あと、データ構造(クラス)を確認すると、

> class(EuStockMarkets_df)
[1] "tbl_df"     "tbl"        "data.frame"

ちゃんとtbl_dfになっています。
(data.frameも表示されているので普通のデータフレーム型としても扱えそうです)


使い方①:filterでほしい行のデータを抽出

方法は、filter(データ名, 条件)という感じ。

やってみると、

> filter(EuStockMarkets_df,  DAX <= 1450)
Error in filter_impl(.data, quo) : matrix as column is not supported

ん、エラーだ。。

意味はmatrixはサポートしてないよーて感じかな。
いやでもtbl_dfに変換しているからmatrixになってないはず。
一応、調べると、

> class(EuStockMarkets_df)
[1] "tbl_df"     "tbl"        "data.frame"

やっぱりmatrixになってない。おかしいなー。

元のサンプルデータは、、、

> class(EuStockMarkets)
[1] "mts"    "ts"     "matrix"

matrixだ。でも、変換してるから関係ないはず。。

んー、なぞだ。これバグでは??

元のサンプルデータがmatrixだから変な挙動してるのかな。

一回、データを書き出して新しいデータとして読み込んで実行してみるか。

> #write.csvでcsvファイルを書き出す *row.names = Fは行番号を書き出さない処理
> write.csv(EuStockMarkets,"C:/Users/mtsuj/data.csv",row.names = F)

> #freadはcsvを高速で読み込む関数
> #*data.tableをインストールしてlibrary(data.table)で読み込む必要
> EuStockMarkets_df <- fread("C:/Users/mtsuj/data.csv") 

> #freadで読み込むとdata.tableとdata.frameのデータ構造になる
> class(EuStockMarkets_df)
[1] "data.table" "data.frame"
> 
> #今のデータ構造でも問題ないが、今回はtbl_dfに変換する
> EuStockMarkets_df <- tbl_df(EuStockMarkets_df)
> class(EuStockMarkets_df)
[1] "tbl_df"     "tbl"        "data.frame"
> 
> #filterでドイツの株価指数が1450以下のものを抽出
> filter(EuStockMarkets_df,  DAX <= 1450)
# A tibble: 6 x 4
      DAX    SMI    CAC   FTSE
    <dbl>  <dbl>  <dbl>  <dbl>
1 1402.34 1788.0 1611.0 2446.3
2 1421.49 1820.5 1612.5 2488.4
3 1434.61 1858.2 1654.2 2517.1
4 1446.32 1870.3 1673.9 2538.8
5 1437.65 1878.4 1657.3 2541.2
6 1441.57 1881.5 1655.1 2557.2

お、いけた。

Rってこうゆうところありますよね。。

他の使い方は次回ご紹介

*使い方編はこちら
R dplyrとはなんぞや?大規模データも簡単に処理? ~使い方~

2017年3月3日金曜日

【トレジャーデータ:Presto】SQLでのクロス集計は?caseとmap_aggならどっち?表頭項目を指定しない方法は?

SQLでのクロス集計は?

SQL(Presto)では、CASE式やmap_agg関数を利用してクロス集計をする方法がある。

CASE式の例はこちらを参照(【トレジャーデータ:Presto】各ユーザの曜日別アクセス率を集計してライフスタイルに合ったアプローチをする)。

また、CASE式以外にもmap_agg関数を使う方法もある。
例えば、下記のようなテーブル(access_log)があるとする。timeはタイムスタンプ。

table:access_log
timecategoryuser_id
1488508906経済記事id2140001
1488508907経済記事id2140001
1488508908物理記事id2140002
1488508909医学記事id2140002
1488508910医学記事id2140001
1488508911文学記事id2140003
1488508912物理記事id2140002
...
...
...

そして、下記のようなコードを書く。

SELECT 

  days,

  --集計したいcategoryの項目を指定する

  COUNT(kv['経済記事']) AS "経済記事",

  COUNT(kv['医学記事']) AS "医学記事",

  COUNT(kv['物理記事']) AS "物理記事",

  COUNT(kv['文学記事']) AS "文学記事"

FROM (

    SELECT 

      TD_TIME_FORMAT(time,

        'yyyy-MM-dd','jst') AS days,

      --map集計:キーと値の重複なしペアをつくる

      map_agg(

        category,

        user_id

      ) kv

    FROM

      access_log

    GROUP BY

      TD_TIME_FORMAT(time,

        'yyyy-MM-dd','jst'),

      category,

      user_id

  )

GROUP BY

  days

このコードを実行すると、表側を日次、表頭を各記事カテゴリとするUU(ユニークユーザ数)を集計することができる。(ここで、ユニークユーザ数となる理由は、map_aggでキーと値で重複なしのペアをつくり、そのデータをもとに集計しているため)
 

time経済記事医学記事物理記事文学記事
2017-03-012527
2017-03-02675363
2017-03-0321674
.....
.....
.....

ただ、map_aggでの集計はメモリを多く使うためデータが大きい場合には適さない。実際、数千万レコード以上のデータを対象に集計をした際、メモリ不足となり集計できなかった(エラーをみると80GB以上のメモリを使っていた)。一方、CASE式で同様の集計したところ問題なくできた。

caseとmap_aggならどっち?

結論としては、CASE式。理由は、計算が速く、メモリ消費も抑えることができるため。一方、map_aggはあまり大規模データのクロス集計に適さないと言える(と、思いますがmap_aggを有効に使う方法があれば教えて頂きたいです)。

表頭項目を指定しない方法は?

case、map_aggも共に表頭項目の指定を一つ一つ記載する必要がある。そのため、項目が未知の場合や項目が膨大にある場合には対応が難しい。そこで、表頭項目を指定しなくてもクロス集計できる方法をいろいろ調べた(ネットで2日くらい探索したりTDの中の人に聞いてみた)が、残念ながら見つからなかった。どうやら、SQL以外の方法で集計するしかなさそう。。

Rでは表頭項目を指定しなくてもクロス集計できる

Rではacast(R クロス集計(acast))やspread(R 高速に大規模データのクロス集計をおこなう(tally, spread))を使えば、一つ一つ表頭項目を指定せずにクロス集計できる。特に、spreadは大規模データでも高速に処理できるため大変オススメ。


。。。SQL上で表頭項目の指定を必要としないクロス集計が簡単にできたら良いのに…
一応、TDの中の人にお願いしておきました。


map_aggの参考サイト

 

2016年11月8日火曜日

【R】data.tableとdplyrの内容が良くまとまっているページ

Rで大規模データの処理をするには、data.tableとdplyrが必須です。
下記のページは、その内容が簡潔にまとめられていて非常に参考になります。

 大規模データの高速処理 ーdata.table、dplyrー
http://kohske.github.io/ESTRELA/201410/index.html

特に、他のサイトではあまり紹介されていないキーの設定の説明があるところ良いです。

setkey(dt, key)

d: データテーブル
key: キーとなるカラム名

これだけでデータ集計が高速に!

2016年8月23日火曜日

R 高速に大規模データのクロス集計をおこなう(tally, spread)

【目的】 Rで高速に大規模データのクロス集計をしたい
【方法】 tallyとspredを使う
【補足】 library(dplyr)とlibrary(tidyr)が必要

df.cross <- df.data %>%
  group_by(x, y) %>%
  tally %>%
  spread(y, n)

#データが無い場合はNAとなるため必要に応じて0にする
df.cross[is.na(df.cross)] <- 0

◇参照URL
クロス集計~公式:dplyr + tidyr = (xtabs|(f)table)
http://d.hatena.ne.jp/teramonagi/20150312/1426109245