#12:Connector for PythonでPandasにデータを読み込む – Snowflake Advent Calendar 2019 #SnowflakeDB
本エントリはSnowflake Advent Calender 2019のエントリです。
データアナリティクス事業本部、池田です。
なんかいろいろありまして勢いでアドベントカレンダーに参加しております。
なんとなくAPI系がよかったので題材を探していたところ、
Python からSnowflakeへ接続する方法がありましたので紹介します。
SnowflakeのエディションはENTERPRISEです。
今回使用するデータ
まずはWebのコンソールから接続してみます。
今回はトライアル版にもある天気のテーブル SNOWFLAKE_SAMPLE_DATA.WEATHER.WEATHER_14_TOTAL
を使用しました。
WEATHERスキーマには複数テーブルがありますが、WEATHER_14_TOTALが実績でそれ以外が予報のようです。
( サンプルの説明 )
また、データがJSONで格納されており、(心が折れかけましたが、)
ハンズオンラボガイドに扱い方があるようで、弊社でも既に ブログ なっていました。
ちなみにこのテーブルのデータは約1時間おきにレコードが追加されるようです。
特定の都市の特定の月の気温と天気の説明を参照する、こんな感じのクエリを書いてみました。
SELECT v:city:name::string AS display_city, -- date_trunc('month', '2019-11-01'::date) AS display_month, DATE_TRUNC('month', CURRENT_DATE()) AS display_month, TO_TIMESTAMP_LTZ(v:time) AS datetime, v:main:temp - 273.15 AS temp, v:weather[0]:description::string AS desc FROM WEATHER_14_TOTAL WHERE v:city:country = 'JP' AND v:city:name = 'Tokyo' AND datetime >= display_month AND datetime < DATEADD('month', 1, display_month) ORDER BY v:time ;
組み込みの関数は リファレンスの一覧 で探しながら書きました。 また、結果ビューに表示される日時のタイムゾーンが太平洋だったので、 東京にするために、 この辺 を参考にタイムゾーンの設定を変えています。
このテーブルの情報をPythonでプロットする辺りまでをやってみます。
Snowflake Connector for Python
ガイド を基にPythonパッケージのインストールなど
環境を準備します。 snowflake-connector-python
パッケージが必要になります。
(私はAnaconda使っているので、condaでパッケージが見つからない時は conda install -c conda-forge snowflake-connector-python
みたいな感じで
別チャンネルから取得する必要がありました。)
Python Connector API に従いながらコードを作成します。
↓結果がこんな感じです。
クリックでコードを表示する/折りたたむ
- 出力(
print(*data, sep="\n")
の一部)
('Tokyo', datetime.date(2019, 12, 1), datetime.datetime(2019, 12, 1, 0, 1, 54, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>), 4.19, 'few clouds') ('Tokyo', datetime.date(2019, 12, 1), datetime.datetime(2019, 12, 1, 1, 1, 55, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>), 3.7, 'few clouds') ('Tokyo', datetime.date(2019, 12, 1), datetime.datetime(2019, 12, 1, 2, 1, 56, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>), 4.49, 'broken clouds') ('Tokyo', datetime.date(2019, 12, 1), datetime.datetime(2019, 12, 1, 3, 2, 45, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>), 4.55, 'broken clouds') ('Tokyo', datetime.date(2019, 12, 1), datetime.datetime(2019, 12, 1, 4, 2, tzinfo=<DstTzInfo 'Asia/Tokyo' JST+9:00:00 STD>), 4.46, 'broken clouds') …
- 出力(
df.info()
)
カラム名が大文字になっていますね。
<class 'pandas.core.frame.DataFrame'> RangeIndex: 229 entries, 0 to 228 Data columns (total 5 columns): DISPLAY_CITY 229 non-null object DISPLAY_MONTH 229 non-null object DATETIME 229 non-null datetime64[ns, UTC] TEMP 229 non-null float64 DESC 229 non-null object dtypes: datetime64[ns, UTC](1), float64(1), object(3) memory usage: 9.1+ KB
Snowflake SQLAlchemy
Snowflake SQLAlchemy を基に実装します。
snowflake-sqlalchemy
と sqlalchemy
パッケージを使います。
↓コードはこんな感じです。
クリックでコードを表示する/折りたたむ
- 出力(
df.info()
)
<class 'pandas.core.frame.DataFrame'> RangeIndex: 230 entries, 0 to 229 Data columns (total 5 columns): display_city 230 non-null object display_month 230 non-null object datetime 230 non-null datetime64[ns, UTC] temp 230 non-null float64 desc 230 non-null object dtypes: datetime64[ns, UTC](1), float64(1), object(3) memory usage: 9.1+ KB
こちらの方法で読み込んだ時はカラム名は小文字になりました。
先述のドキュメントによると
Snowflake stores all case-insensitive object names in uppercase text. In contrast, SQLAlchemy considers all lowercase object names to be case-insensitive.
らしいです。へー。
SQLAlchemyっぽい書き方をしてみる
せっかくなので、っぽい書き方で接続してみました。 (WEATHERスキーマのJSONのテーブルだと苦労しそうだったので、別のテーブルを使っています。)
↓コードはこんな感じです。
クリックでコードを表示する/折りたたむ
- 出力(
print(*my_items, sep='\n')
)
224558, AAAAAAAAOCNGDAAA, Dominant, implicit months ought to join. Alone p, Music 224559, AAAAAAAAOCNGDAAA, Structural times must consider often, Electronics
ORMっぽい。
おわりに
チュートリアルなど一切やれていないまま勢いでとりあえず触ってみましたが、 (英語ですが)ドキュメントも充実していてやりたいことはできました。 あとはクエリのレスポンスが早くて、すごいなー、へー、と思いました。 でも今回一番驚いたのは、東京の気温の低さです。こんなに寒くなっていたとは思ってませんでした…
で、明日13日の金曜日は 甲木 洋介 がもたらす 恐怖と戦慄の「#13:SnowflakeのALTER TABLE SWAPが超絶的に便利だった件」 の予定です。
参考文献
SQLAlchemy関連です。