32
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

今さら聞けないPython - pandasを用いたデータ分析

Last updated at Posted at 2023-03-28

こちらのウェビナーで説明した内容の抜粋です。最初のセクションの「pandasを用いたデータ分析」をカバーしています。今さら聞けないPython - Pythonの基礎の続きです。

全体構成は以下の通りです。

ウェビナーで使用したノートブックはこちらにあります。

本記事でカバーしているノートブックはこちらです。

  • pandasを使う動機づけ
  • pandasとその歴史
  • COVID-19データセットのインポート
    • pd.read_csv()
  • データの要約
    • head, tail, shape
    • sum, min, count, mean, std
    • describe
  • データのスライスと加工
    • スライス, loc, iloc
    • value_counts
    • drop
    • sort_values
    • フィルタリング
  • データのグルーピングおよび集計関数の実行
    • groupby
  • 欠損値、重複への対応
    • isnull
    • unique, drop_duplicates
    • fillna
  • 可視化
    • ヒストグラム
    • 散布図
    • 折れ線グラフ

pandasを使う動機づけ

大きな絵からスタートしましょう...

  • 人類は道具を使う動物です
  • コンピューターは我々が作り出した最もパワフルなツールの一つです
  • コードを書くことで、これらのツールのフルパワーを解き放つことができます

Ok、クールだね。でもなぜpandas?

  • これまで以上にデータは意思決定において重要となっています。

  • Excelは素晴らしいものですが、もし...

    • 毎日新規のデータに対して再実行できるように分析を自動化したいとしたら?
    • 同僚と共有できるようにコードベースを構築したいとしたら?
    • ビジネス上の意思決定につながるより堅牢な分析を必要としたら?
    • 機械学習を行いたいとしたら?
  • Pythonにおけるデータ分析やデータサイエンティストによって使用されるコアのライブラリの一つが

    pandasにようこそ...

pandasとその歴史

pandasは、Pythonプログラミング言語上で開発された、高速、パワフル、柔軟かつ、簡単に使用できるオープンソースのデータ分析、データ操作ツールです。

ハイライト:

  • 2008年に開発され、2009年にオープンソース化されました。
  • インデックスがインテグレーションされたデータ操作のための高速かつ効率的なデータフレームオブジェクト
  • インメモリーのデータ構造と様々なフォーマット間のデータ読み書きツール: CSV、テキストファイル、Microsoft Excel、SQLデータベース、高速なHDF5フォーマット。
  • インテリジェントなデータアライメントとインテグレーションされた欠損データへの対応: 計算時に自動でラベルベースのアライメントを取得し、汚いデータを容易に綺麗な状態に変換。
  • データセットに対する柔軟な リシェイプとピボット
  • 大規模データセットに対するインテリジェントなラベルベースの スライス、ファンシーインデックス、サブセット作成
  • サイズ可変性を持つデータ構造に対するカラムの追加・削除。
  • パワフルなgroup byを用いたデータの集計、変換によるデータセットに対するsplit-apply-combineオペレーション。
  • データセットに対する高性能のマージとジョイン
  • 階層型軸インデックスによる、低次元データ構造における直感的な高次元データ操作手段の提供。
  • 時系列機能: 日付範囲の生成、頻度変換、移動ウィンドウ統計情報、日付シフト、ラギング。ドメイン固有の時間オフセットの作成、データ損失なしの時系列データのジョインもサポート。
  • Cython、Cで記述されたクリティカルなコードパスにより高度に最適化されたパフォーマンス。
  • Pythonとpandasは、金融、神経科学、経営、統計学、広告、Web分析などを含むさまざまな学術、商用の領域で活用されています。

COVID-19データセットのインポート

フォルダー構造を検索するために %sh ls を使います。%shはDatabricksノートブックでシェルコマンドを実行することができるマジックコマンドです。

%sh ls /dbfs/databricks-datasets/COVID/
CORD-19
CSSEGISandData
ESRI_hospital_beds
IHME
USAFacts
coronavirusdataset
covid-19-data
download_daily_covid-19_datasets.sh
estimated_patient_impact_and_hospital_capacity_by_state
%sh ls /dbfs/databricks-datasets/COVID/CSSEGISandData/csse_covid_19_data/csse_covid_19_daily_reports
01-01-2021.csv
01-02-2021.csv
01-03-2021.csv
01-04-2021.csv
01-05-2021.csv
01-06-2021.csv
01-07-2021.csv
01-08-2021.csv
01-09-2021.csv
01-10-2021.csv

CSVファイルの最初の数行を表示するために %sh head を使います。

%sh head /dbfs/databricks-datasets/COVID/CSSEGISandData/csse_covid_19_data/csse_covid_19_daily_reports/04-11-2020.csv
FIPS,Admin2,Province_State,Country_Region,Last_Update,Lat,Long_,Confirmed,Deaths,Recovered,Active,Combined_Key
45001,Abbeville,South Carolina,US,2020-04-11 22:45:33,34.22333378,-82.46170658,9,0,0,0,"Abbeville, South Carolina, US"
22001,Acadia,Louisiana,US,2020-04-11 22:45:33,30.295064899999996,-92.41419698,98,4,0,0,"Acadia, Louisiana, US"
51001,Accomack,Virginia,US,2020-04-11 22:45:33,37.76707161,-75.63234615,15,0,0,0,"Accomack, Virginia, US"
16001,Ada,Idaho,US,2020-04-11 22:45:33,43.4526575,-116.24155159999998,513,6,0,0,"Ada, Idaho, US"
19001,Adair,Iowa,US,2020-04-11 22:45:33,41.33075609,-94.47105874,1,0,0,0,"Adair, Iowa, US"

pandasをインポートします。別名をpdとします。

Python
import pandas as pd

CSVファイルを読み込みます。これによってデータフレームが生成されます。1行目のコマンドではファイルシステムユーティリティを用いてファイルをローカルにコピーしています。

Python
dbutils.fs.cp("dbfs:/databricks-datasets/COVID/CSSEGISandData/csse_covid_19_data/csse_covid_19_daily_reports/04-11-2020.csv", "file:/tmp/covid.csv")
pd.read_csv("file:/tmp/covid.csv")

Screenshot 2023-03-28 at 16.37.29.png

それでは数行のコードを組み合わせて、再利用できるようにデータフレームを保存してみましょう。

Python
import pandas as pd

df = pd.read_csv("file:/tmp/covid.csv")

df

Screenshot 2023-03-28 at 16.37.29.png

データの要約

データの最初の数行と最後の数行を見てみましょう。

Python
df.head()

Screenshot 2023-03-28 at 16.43.06.png

Python
df.tail(2)

Screenshot 2023-03-28 at 16.44.11.png

データセットは何行でしょうか?

Python
df.shape
Out[10]: (2967, 12)

データを要約しましょう。

Python
# df.sum()
# df.min()
# df.max()
# df.count()
df.mean()
# df.std()
Out[11]: FIPS         31172.744602
Lat             36.564846
Long_          -80.663000
Confirmed      584.822042
Deaths          36.747893
Recovered      135.600944
Active         259.575666
dtype: float64

これらのサマリー統計情報を集計して表示することができます...

Python
df.describe()

Screenshot 2023-03-28 at 16.48.36.png

データのスライスと加工

感染者数だけを取り出します。

Python
df['Confirmed']
Out[13]: 0         9
1        98
2        15
3       513
4         1
       ... 
2962    268
2963      1
2964     40
2965     14
2966      0
Name: Confirmed, Length: 2967, dtype: int64

国と感染者数を取り出します。その前に、データフレームの列名を取得します。

Python
df.columns
Out[14]: Index(['FIPS', 'Admin2', 'Province_State', 'Country_Region', 'Last_Update',
       'Lat', 'Long_', 'Confirmed', 'Deaths', 'Recovered', 'Active',
       'Combined_Key'],
      dtype='object')
Python
df[['Country_Region', 'Confirmed']]

Screenshot 2023-03-28 at 16.57.19.png

新たなカラム Date を作成します。

Python
import datetime

df["Date"] = datetime.date(2020, 4, 11)

df["Date"].head()
Out[17]: 0    2020-04-11
1    2020-04-11
2    2020-04-11
3    2020-04-11
4    2020-04-11
Name: Date, dtype: object

データフレームの最初の11行を取り出してスライスします。

Python
df.loc[:10, ['Country_Region', 'Confirmed']]
# df.loc[0:10, ['Country_Region', 'Confirmed']] # 同じ処理です

Screenshot 2023-03-28 at 17.00.52.png

最初の行の最初のカラムだけを返却します。

Python
df.iloc[0, 0]
Out[19]: 45001.0

国ごとにいくつの地域があるのでしょうか?value_countsを使用して、値ごとのカウントをとります。

Python
df["Country_Region"].value_counts()
Out[20]: US                2702
China               33
Canada              16
United Kingdom      12
France              11
                  ... 
Georgia              1
Germany              1
Ghana                1
Greece               1
Zimbabwe             1
Name: Country_Region, Length: 185, dtype: int64

FIPSとはなんでしょうか?ここでは不要なので削除します。dropの引数axis=1は列方向であることを指定しています。

Python
df = df.drop("FIPS", axis=1)

感染者数でソートします。引数ascending=Falseは降順を指定しています。

Python
df.sort_values("Confirmed", ascending=False)

Screenshot 2023-03-28 at 17.09.43.png

アメリカ(US)で起きていることだけを見てみましょう。

Python
df[df["Country_Region"] == "US"]

Screenshot 2023-03-28 at 17.10.48.png

データのグルーピングと集計関数の実行

感染者数が最も多い国はどこでしょうか?データをグルーピングし合計を計算します。集計関数はスカラー値(単一の値)を返却することに注意してください。

Country_Regionをキーにグルーピングを行い、グループごとの感染者数Confirmed
の合計をsum()で取得し、感染者数合計の降順で表示します。

Python
df.groupby("Country_Region")["Confirmed"].sum().sort_values(ascending=False)
Out[26]: Country_Region
US                  526764
Spain               163027
Italy               152271
Germany             124908
France               93909
                     ...  
South Sudan              4
Timor-Leste              2
Papua New Guinea         2
Yemen                    1
Samoa                    0
Name: Confirmed, Length: 185, dtype: int64

感染者数が最も多いUSの州はどこでしょうか?フィルタリング条件を追加し、Province_Stateごとに集計します。

Python
df[df['Country_Region'] == "US"].groupby("Province_State")["Confirmed"].sum().sort_values(ascending=False)
Out[27]: Province_State
New York                    181026
New Jersey                   58151
Michigan                     23605
Massachusetts                22860
Pennsylvania                 21719
California                   21711
Louisiana                    20014
Illinois                     19180
Florida                      18494
Texas                        13145
Georgia                      12159
Connecticut                  11510

欠損データと重複への対応

null値はあるのでしょうか?

Python
df.isnull().tail()

Screenshot 2023-03-28 at 17.16.30.png

sum()でnull値の数を取得することができます。

Python
df.isnull().sum()
Out[29]: Admin2            272
Province_State    181
Country_Region      0
Last_Update         0
Lat                58
Long_              58
Confirmed           0
Deaths              0
Recovered           0
Active              0
Combined_Key        0
Date                0
dtype: int64
PYthon
df['Country_Region'].unique().shape
Out[30]: (185,)

null値を特定の値で置き換えることもできます。

Python
df.fillna("NO DATA AVAILABLE").tail(3)

可視化

  • ヒストグラム
  • 散布図
  • 折れ線グラフ
Python
import matplotlib.pyplot as plt

%matplotlib inline

us_subset_df = df[df["Country_Region"] == "US"]

USの州と地域ごとの死者数の 分布 はどうなっているのでしょうか?

Python
us_subset_df.groupby("Province_State")["Deaths"].sum().hist(bins=30)

Screenshot 2023-03-28 at 17.25.19.png

死者数に比べて感染者数はどうなっているのでしょうか?

Python
us_subset_df[us_subset_df["Deaths"] < 1000].plot.scatter(x="Confirmed", y="Deaths")

Screenshot 2023-03-28 at 17.26.12.png

複数の日のデータをインポートします。

Python
src_path_base = "dbfs:/databricks-datasets/COVID/CSSEGISandData/csse_covid_19_data/csse_covid_19_daily_reports/"
dest_path_base = "file:/tmp/covid_daily_reports/"

files = [
 '11-21-2020.csv',
 '11-22-2020.csv',
 '11-23-2020.csv',
 '11-24-2020.csv',
 '11-25-2020.csv',
 '11-26-2020.csv',
 '11-27-2020.csv',
 '11-28-2020.csv',
 '11-29-2020.csv',
 '11-30-2020.csv'
]

dfs = []

for file in files:
  filename = dest_path_base+file
  dbutils.fs.cp(src_path_base+file, filename)
  
  temp_df = pd.read_csv(filename)
  temp_df.columns = [c.replace("/", "_") for c in temp_df.columns]
  temp_df.columns = [c.replace(" ", "_") for c in temp_df.columns]
  
  month, day, year = filename.split("/")[-1].replace(".csv", "").split("-")
  d = datetime.date(int(year), int(month), int(day))
  temp_df["Date"] = d

  dfs.append(temp_df)
  
all_days_df = pd.concat(dfs, axis=0, ignore_index=True, sort=False)
all_days_df = all_days_df.drop(["Lat", "Long_", "FIPS", "Combined_Key", "Last_Update"], axis=1)

時間と共に感染病はどのように広がったのでしょうか?

Python
all_days_df.groupby("Date")["Confirmed"].sum().plot(title="Confirmed Cases over Time", rot=45)

Screenshot 2023-03-28 at 17.27.54.png

これをケースのタイプごとにブレークダウンします。

Python
all_days_df.groupby("Date")["Confirmed", "Deaths", "Recovered"].sum().plot(
    title="Confirmed, Deaths, Recovered over Time", rot=45
)

Screenshot 2023-03-28 at 17.28.34.png

特定の場所における増加状況はどうなっているでしょうか?

Python
(
    all_days_df[
        (all_days_df["Country_Region"] == "US")
        & (all_days_df["Province_State"] == "California")
        & (all_days_df["Admin2"] == "San Francisco")
    ]
    .groupby("Date")["Confirmed", "Deaths", "Recovered"]
    .sum()
    .plot(title="Confirmed, Deaths, Recovered over Time", rot=45)
)

Screenshot 2023-03-28 at 17.29.19.png

このように、pandasデータフレームを活用することで柔軟にデータ分析を行うことができます。

今さら聞けないPython - scikit-learnを用いた機械学習に続きます。

Databricksクイックスタートガイド

Databricksクイックスタートガイド

Databricks無料トライアル

Databricks無料トライアル

32
50
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?