Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
『改訂新版前処理大全』の話と Apache Parquet の話 #TokyoR
Search
bob3bob3
June 08, 2024
Programming
1.5k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
『改訂新版前処理大全』の話と Apache Parquet の話 #TokyoR
『改訂新版前処理大全』のR言語版サンプルコードとApache parquetによる高速化の話。 #TokyoR
bob3bob3
June 08, 2024
More Decks by bob3bob3
See All by bob3bob3
RとLLMで自然言語処理
bob3bob3
3
910
RでPSM分析
bob3bob3
1
450
Rでコンジョイント分析 2024年版
bob3bob3
0
2.4k
R言語の環境構築と基礎 Tokyo.R 112
bob3bob3
0
650
『データ可視化学入門』をPythonからRに翻訳した話(増強版)
bob3bob3
0
590
『データ可視化学入門』を PythonからRに翻訳した話
bob3bob3
1
670
qeMLパッケージの紹介
bob3bob3
0
2.7k
「国と音楽」 ~spotifyrを用いて~ #muana
bob3bob3
2
660
パーマーステーションのペンギンたち#3 探索的データ分析(EDA)編
bob3bob3
1
860
Other Decks in Programming
See All in Programming
C# and C++ Interoperability - cho-dotnetnew
harukasao
0
160
Javaの型とAI時代に型が大事な理由 / java types and type in AI era
kishida
2
140
Datadog × OpenTelemetry 入門と実践のあいだ
kn_to_maxpno
1
160
Agentic UI
manfredsteyer
PRO
0
170
コンテキストの使い捨てをやめる — ビジネスルール駆動開発と miko —
ioki
0
210
Lemonade + Foundry Toolkit でお手軽アプリ開発
seosoft
1
360
ADKを使って簡単にAIエージェントを作ってみよう
k1mu21
0
270
JavaDoc 再入門
nagise
1
370
Contextとはなにか
chiroruxx
1
330
Honoでのサプライチェーン侵害対策 〜 3つのライブラリに学ぶ
yusukebe
6
1.3k
Skillsは効率化、Agentsは"自分の拡張"——Builder時代のエージェント編成(CC Night 2026)
wemra
1
140
Make SRE Operations Easier with Azure SRE Agent
kkamegawa
0
6.6k
Featured
See All Featured
Amusing Abliteration
ianozsvald
1
210
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
370
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
440
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
1.7k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.5k
From π to Pie charts
rasagy
0
210
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
160
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
750
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.2k
Transcript
『改訂新版前処理大全』の話と Apache Parquet の話 Tokyo.R #113 2024/06/08 @bob3bob3
『改訂新版前処理大全』 • 2018年に発売されてデータ分析界隈で 大きな話題となった『前処理大全』のアッ プデート版。 • データサイエンスに取り組む上で欠かせ ない前処理の効率的な処理方法を網羅 的に習得できる構成。 •
サンプルデータがApache Parquet形式 で提供されているのも特徴。 • 旧版ではR、Python、SQLを用いた実装 方法を紹介していたが、改訂新版では BigQuery準拠のSQL、最新バージョンの Pandas、Rの代わりに高速なPolarsに変 更しました。
『改訂新版前処理大全』 Rの代わりに高 速なPolarsに変 更しました。
というわけで、Rで『改訂新版前処理大全』 のサンプルコードを書いています。
例1
例1)ビジネスホテルかつ宿泊人数が1名の予約履歴の抽出 reservation(200万件、11列) hotel(5千件、39列)
例1)ビジネスホテルかつ宿泊人数が1名の予約履歴の抽出 reservation(200万件、11列) hotel(5千件、39列)
例1)ビジネスホテルかつ宿泊人数が1名の予約履歴の抽出 # Not Awesome reservation |> inner_join(hotel, by = "hotel_id")
|> dplyr::filter(hotel_type == "ビジネスホテル" & people_num == 1) # Awesome reservation |> dplyr::filter(people_num == 1) |> inner_join( hotel |> dplyr::filter(hotel_type == "ビジネスホテル") |> select(hotel_id), by = "hotel_id" )
例1)ビジネスホテルかつ宿泊人数が1名の予約履歴の抽出 # Not Awesome reservation |> inner_join(hotel, by = "hotel_id")
|> dplyr::filter(hotel_type == "ビジネスホテル" & people_num == 1) reservationとhotelをすべて結合してから条件指定によってデータの抽出を行っている。 また必要な列に絞らずhotelマスターのすべての列を出力している。
例1)ビジネスホテルかつ宿泊人数が1名の予約履歴の抽出 # Awesome reservation |> dplyr::filter(people_num == 1) |> inner_join(
hotel |> dplyr::filter(hotel_type == "ビジネスホテル") |> select(hotel_id), by = "hotel_id" ) reservationとhotelそれぞれを必要な行と列に絞ってからjoinしている。
例1)ビジネスホテルかつ宿泊人数が1名の予約履歴の抽出 Awesomeなコードの方が中央値で6倍 ぐらい速い。 joinする前にそれぞれのデータをできる 限り小さくしておくこと!
Apache Parquet による前処理の高速化
Apache Parquet による前処理の高速化 • Apache Parquet はオープンソースの列指向データファイルフォーマットで、効率的 なデータの保存と検索のために設計されています。 • 複雑なデータを一括処理するための高性能な圧縮とエンコード方式を提供し、多く
のプログラミング言語と分析ツールでサポートされています。 • Rではarrowパッケージで Apache Parquet を扱うことができます。
Apache Parquet による前処理の高速化 # データフレームとして reservation_df <- read_parquet( "https://github.com/ghmagazine/awesomebook_v2/raw/main/data/reservation.parquet" )
# Arrow Table として reservation_at <- read_parquet( "https://github.com/ghmagazine/awesomebook_v2/raw/main/data/reservation.parquet", as_data_frame = FALSE ) parquet形式のデータをarrowパッケージのread_parquet()関数で読み込む。 デフォルトではデータフレームとして読み込まれるが、引数に as_data_frame = FALSE を付けるとArrow Tableとして読み込まれる。
Apache Parquet による前処理の高速化 # データフレームの処理 reservation_df |> dplyr::filter(status != "canceled")
|> summarise(reservation_cnt = n(), .by = c(hotel_id, customer_id)) # Arrow Table の処理 reservation_at |> dplyr::filter(status != "canceled") |> summarise(reservation_cnt = n(), .by = c(hotel_id, customer_id)) |> collect() #この処理が加わっただけ ホテルごと顧客ごとの予約数の集計処理。 Arrow Table も tidyverse で処理できるが、最後に collect()を実行することで結果が得られる。
Apache Parquet による前処理の高速化 中央値で約35倍の速さ! Tidyverseのすべての機能が ApacheParquetで使えるわけではない ようですが、積極的に使っていきましょ う! eitsupiさんの以前の発表やuriboさんの 資料もご参考に。
Apache Parquet の資料 @eitsupi さん @uribo さん https://eitsupi.github.io/tokyorslide/tokyor_97 https://uribo.quarto.pub/hello-r-arrow/
例2
例2)予約履歴データに対象キャンペーン情報を付与 reservation(200万件、11列) campaign(30件、3列)
例2)予約履歴データに対象キャンペーン情報を付与 reservation(200万件、11列) campaign(30件、3列)
例2)予約履歴データに対象キャンペーン情報を付与 # Not Awesome reservation |> cross_join(campaign) |> dplyr::filter(reserved_at >=
starts_at & reserved_at <= ends_at) |> select(!c(starts_at, ends_at)) # Awesome campaign_expanded <- campaign |> rowwise() |> mutate(reserve_date = list(seq(date(starts_at), date(ends_at), by="day"))) |> unnest(reserve_date) reservation |> mutate(reserve_date = date(reserved_at)) |> left_join(campaign_expanded, by = "reserve_date",relationship = "many-to-many") |> select(!reserve_date)
# Not Awesome reservation |> cross_join(campaign) |> dplyr::filter(reserved_at >= starts_at
& reserved_at <= ends_at) |> select(!c(starts_at, ends_at)) 例2)予約履歴データに対象キャンペーン情報を付与 予約履歴にキャンペーンマスターをクロス結合、その後キャンペーン期間の行のみを抽 出。最後に不要な列を削除。
# Awesome campaign_expanded <- campaign |> rowwise() |> mutate(reserve_date =
list(seq(date(starts_at), date(ends_at), by="day"))) |> unnest(reserve_date) reservation |> mutate(reserve_date = date(reserved_at)) |> left_join(campaign_expanded, by = "reserve_date",relationship = "many-to-many") |> select(!reserve_date) 例2)予約履歴データに対象キャンペーン情報を付与 キャンペーンマスターにキャンペーン期間のすべての日付の列を追加。 日付をキーに予約履歴にキャンペーンマスターを結合。
例2)予約履歴データに対象キャンペーン情報を付与 Awesomeなコードの方がおよそ6倍速い!
全編はこちらで順次公開予定 https://morimotoosamu.github.io/awesomebook_v2/
Enjoy!