Open4

Python実践データ分析100本ノック 第2版での学びのメモ

jimatomojimatomo

書くこと

補足的にコードの内容でやっていることを深堀した時のメモを書いておきます。
なるべく本のコアの内容に触れないようにPythonでデータ分析系のコード書く時の一般的なポイントをメモしていく感じです。
興味があれば買って手を動かしてみるといいかなと思います。

https://www.shuwasystem.co.jp/book/9784798067278.html

jimatomojimatomo

そもそも環境構築について

Google Colaboratoryを使うように紹介されていますが、今回はPC上にWSL2 + Docker Desktop + VS CodeのDevContainerを利用して、Jupyterのプラグインを導入した開発環境を利用していきます(たぶん大丈夫だと思いますが、うまくいかなかったらその時トラブルシューティングします)

Dockerfile
FROM python:3

RUN apt-get update
RUN pip install --upgrade pip
RUN python -m pip install cmake
RUN python -m pip install numpy pandas matplotlib scikit-learn networkx scipy pulp ortoolpy dlib tensorflow xmltodict absl-py japanize-matplotlib opencv-python mecab-python3 openpyxl
RUN python -m pip install jupyter

※openpyxlがないと怒られたので追加(2023/4/9)

専用のフォルダを切って、そこにサンプルデータやノートブックのファイルが入ったzipを解凍して配置します。そこにDockerfileを配置してDevContainerを起動します。

cmakeはdlibのインストールに必要です。
https://self-development.info/【python】dlibのインストール/

Pythonのバージョンは3.11.3でした。

jimatomojimatomo

第1章 ウェブからの注文数を分析する10本ノック

pandasの基本操作を使ってUNIONやJOINとか実施。
データ型の変換や加工処理、そのほかにもGroup Byなどの基本的な集計操作やpivot tableを利用した変換などを実施して、最後にmatplotlibでグラフ化まで実施するというものでした。

ちゃんとデータの加工が意図した通りにできているかを確認するという単に技術だけでなく大事な考え方を書いているのがいいですね。第2版まで出ている人気の本である理由に触れた気がします。

ポイント

以下を学びました。

  • pandasでcsvファイルを読み込む方法
  • pandasでconcat (UNION) する方法
  • pandasでmerge (JOIN) する方法
  • DataFrameから列を抽出し計算して列を追加する方法
  • 検算の大切さ
  • DataFrameの欠損値の確認方法
  • DataFrameの統計量の確認方法
  • Pandasのデータ型を変換する方法(datetimeへの変換)
  • DataFrameの列から年月の文字列を抽出する方法
  • DataFrameでGroupByする方法
  • Pandasでピボットテーブルで変換する方法
  • matplotlib.pyplotでグラフを描画する方法

備忘

pandasのバージョンの違いなのか、DataFrameのGroupBy.sum関数を使うところでFutureWarningが出ました。(ちなみに実機が1.5.3で、本のバージョンが1.3.5でした。)

FutureWarning: The default value of numeric_only in DataFrameGroupBy.sum is deprecated. In a future version, numeric_only will default to False. Either specify numeric_only or select only columns which should be valid for the function. join_data.groupby("payment_month").sum()["price"]

この辺りは以下のようにカラムを絞るようなコードを修正しました。

join_data.loc[:,["payment_month", "price"]].groupby("payment_month").sum()["price"]
jimatomojimatomo

第1章 ウェブからの注文数を分析する10本ノック Polars版

Pandasはググればだいたいやりたいことができるので、すばらしくいい技術で枯れている感があります(5年前くらいの知識がまだまだ生かせる)

ただ触り始めた当時から思っていましたが、メモリあふれたり、一部処理が遅かったりするので、最近はPandasより速いという噂のPolarsを触ってみたいなと思っていました。今回はこの本のノックを題材としてPolarsで書き直してみたいと思います。
(巷ではデータサイエンス100本ノックを解いてみた記事もあるので、たぶんできるはず)
https://qiita.com/_jinta/items/fac13f09e8e8a5769b79

ただ、あまりがっつり書いてしまうとほんのネタバレになるので、コードだけ貼る感じにします。

まずはインストールします。

pip install polars

コードはこちら(一部のみ)

import polars as pl

# pandasでcsvファイルを読み込む方法
cumstomer_master = pl.read_csv('customer_master.csv')

#pandasでconcat (UNION) する方法
transaction = pl.concat([transaction_1, transaction_2], how="vertical")

#pandasでmerge (JOIN) する方法
join_data = transaction.select(
    pl.col(['transaction_id', 'payment_date', 'customer_id'])
  ).join(
    transaction_detail,
    left_on="transaction_id",
    right_on="transaction_id"
  )

#DataFrameから列を抽出し計算して列を追加する方法
join_data = join_data.with_columns([
  (
    pl.col('quantity') * pl.col('item_price')
  ).alias('price')
])

#検算の大切さ
join_data.select(pl.col('price')).sum() == transaction.select(pl.col('price')).sum()

#DataFrameの欠損値の確認方法
join_data.select(
  pl.col("*").is_null().sum()
)

#DataFrameの統計量の確認方法
join_data.describe()

#Pandasのデータ型を変換する方法(datetimeへの変換)
join_data_cast_timestamp = join_data_4.with_columns(
  [
    pl.col('payment_date').str.strptime(pl.Datetime)
  ]
)

#DataFrameの列から年月の文字列を抽出する方法
join_data_cast_timestamp = join_data.with_columns(
  [
    pl.col('payment_date').str.strptime(pl.Datetime)
  ]
)

join_data_with_payment_month = join_data_cast_timestamp.with_columns(
  [
    pl.col('payment_date').dt.strftime("%Y%m").alias('payment_month')
  ]
)

# 繋げて、こっちでもいい
join_data_with_payment_month = join_data.with_columns(
  pl.col('payment_date').str.strptime(pl.Datetime)
).with_columns(
  pl.col('payment_date').dt.strftime('%Y%m').alias('payment_month')
)

#DataFrameでGroupByする方法
join_data_with_payment_month.select(
  pl.col(["payment_month", "price"])
).groupby(
  "payment_month"
).agg(
  [
    pl.sum("price").suffix("_sum")
  ]
).sort("payment_month")

#Pandasでピボットテーブルで変換する方法
join_data_with_payment_month.pivot(
  values=["price", "quantity"],
  index="item_name",
  columns="payment_month",
  aggregate_function="sum"
)

#matplotlib.pyplotでグラフを描画する方法
graph_data = join_data_with_payment_month.pivot(
  values='price',
  index='payment_month',
  columns='item_name',
  aggregate_function='sum'
).sort("payment_month")
graph_data.head()

import matplotlib.pyplot as plt

%matplotlib inline
plt.plot(graph_data['payment_month'], graph_data['PC-A'], label='PC-A')
plt.plot(graph_data['payment_month'], graph_data['PC-B'], label='PC-B')
plt.plot(graph_data['payment_month'], graph_data['PC-C'], label='PC-C')
plt.plot(graph_data['payment_month'], graph_data['PC-D'], label='PC-D')
plt.plot(graph_data['payment_month'], graph_data['PC-E'], label='PC-E')
plt.legend()