pandas1

Streamlit入門 – 7)Pandasの基礎

Streamlit入門の7回目です。Streamlitを使う上でPandasができると表現の幅が大幅に広がります。教室ではPandasの教材も用意していますが、ここでは必要最低限のPandasの復習をしてみようと思います。

この記事はFuture Coders独自教材からの抜粋です。

Pandasは表形式のデータを扱うモジュールです。機械学習はデータの可視化など、いろいろなところで利用されています。内容は複雑で多岐にわたりますが、ここでは基本的な内容について説明します。

Pandasでは表形式のデータを扱います。表形式のデータはDataFrameというオブジェクトで管理されます。

下左図にあるように、DataFrameはcolumns(列), index(行), values(データ)から構成されます。

pandas1
Streamlit入門 – 7)Pandasの基礎 7

右図にあるように、DataFrameから1行もしくは1列を取り出したものをSeriesと呼びます。複数行、複数列を取り出した場合、取り出したデータはDataFrameとなります。

データの取得

Pandasで作業をするには、まずDataFrameオブジェクトを作成する必要があります。ここでは、サンプルデータを読み込む方法、外部データを読み込む方法、自分で作成する方法について説明します。

サンプルデータを読み込む

Pandasと関連するライブラリに以下のようなものがあります。これらのライブラリにはサンプルデータが含まれています。

  • seaborn = グラフで可視化するモジュール
  • scikit-learn = 機械学習のモジュール

ここではseabornのサンプルデータからデータフレームを作成する方法を紹介します。まず、含まれているサンプル一覧は以下のコードで確認できます。

import seaborn as sns
print(sns.get_dataset_names())

以下が出力です。

['anagrams', 'anscombe', 'attention', 'brain_networks', 'car_crashes', 'diamonds', 'dots', 'dowjones', 'exercise', 'flights', 'fmri', 'geyser', 'glue', 'healthexp', 'iris', 'mpg', 'penguins', 'planets', 'seaice', 'taxis', 'tips', 'titanic']

さまざまなデータセットが含まれていることがわかります。サンプルデータを読み込むにはseabornのload_dataset関数を使用します。引数にデータセット名を指定します。戻り値がデータフレームとなります。

import pandas as pd
import seaborn as sns
df = sns.load_dataset("iris")
print(df)

データの確認

データフレームを作成したら、まずはデータの確認です。headやtailを使って表の中身を見てみましょう。

  • 先頭の数行の確認 = head(行数) – 省略時は5行
  • 末尾の数行の確認 = tail(行数) – 省略時は5行
  • 行と列の数 = shape
import seaborn as sns
df = sns.load_dataset("iris")
print(df.head())
print(df.tail(3))
print(df.shape)

出力は以下の通りです。

   sepal_length  sepal_width  petal_length  petal_width species
0           5.1          3.5           1.4          0.2  setosa
1           4.9          3.0           1.4          0.2  setosa
2           4.7          3.2           1.3          0.2  setosa
3           4.6          3.1           1.5          0.2  setosa
4           5.0          3.6           1.4          0.2  setosa
     sepal_length  sepal_width  petal_length  petal_width    species
147           6.5          3.0           5.2          2.0  virginica
148           6.2          3.4           5.4          2.3  virginica
149           5.9          3.0           5.1          1.8  virginica
(150, 5)

外部データの読込み

Pandasでは外部ファイルからデータを読み込んでデータフレームを作成することも可能です。CSV、Excel、JSONなどから読み込むことが多いでしょう。

  • read_csv
  • read_excel
  • read_json

これらの関数には数多くの引数が指定できます。利用頻度の高そうな引数を以下に列挙します。

  • usecols = 列を抽出するときに列番号をリスト形式で指定
  • skiprows = 先頭から指定した行数をスキップ
  • nrows = 読み込む行数
  • encoding = エンコーディング, Excelを意識して作られたファイルの場合はShift_JISを指定
  • parse_dates = 日付関連の情報を含む列名をリストで指定

CSVファイルからデータフレームを作成する例を見てみましょう。

東京電力では以下のURLで電力使用状況のデータ(CSV形式)を公開しています。

https://www.tepco.co.jp/forecast/html/download-j.html

2023/8/6 5:40 UPDATE

DATE,TIME,実績(万kW)
2022/1/1,0:00,3266
2022/1/1,1:00,3062
2022/1/1,2:00,2929
...

以下はこのCSVファイルからDataFrameを作成するサンプルです。先頭の2行は概要説明なのでスキップします。またファイルのエンコード形式がShift_JISなのでencoding引数でShift_JISを指定しています。

import pandas as pd
df = pd.read_csv("data/juyo-2022.csv", 
    encoding="Shift_JIS", skiprows=2, parse_dates=["DATE"])
print(df.head(3))

出力結果は以下の通りです。

        DATE  TIME  実績(万kW)
0 2022-01-01  0:00     3266
1 2022-01-01  1:00     3062
2 2022-01-01  2:00     2929

自分で作成

配列から作成

表は縦と横の2次元から構成されるため、2次元配列(リストのリスト)を使ってデータを管理することも多いでしょう。2次元配列を引数に渡すことでDataFrameを作成することができます。列名を指定する場合は、columns引数にリスト形式で列名を渡します。

以下は2次元配列を引数としてDataFrameを作成するサンプルです。

import pandas as pd
df = pd.DataFrame([
        ["apple",100,"red"],
        ["kiwi",200,"brown"],
        ["melon",800,"green"]
    ],
    columns=["fruits", "price", "color"])
print(df)

出力は以下の通りです。

  fruits  price  color
0  apple    100    red
1   kiwi    200  brown
2  melon    800  green

辞書から作成

列名がキー、実際のデータが値と考えると、辞書形式でデータを記述することも可能です。DataFrameは最初の引数に辞書オブジェクトを指定することで作成することもできます。

以下は辞書型のデータを引数としてDataFrameを作成するサンプルです。

import pandas as pd
df = pd.DataFrame(
    {
        "fruits":["apple","kiwi","melon"],
        "price":[100,200,800],
        "color":["red","brown","green"],
    })
print(df)

出力は前の例と同じになります。

データの抽出

列の選択

DataFrameでは特定の列を取り出す作業を頻繁に行います。以下のようにデータフレーム(df)に[]演算子を適用することで列を取り出すことができます。

  • df[“列名”] = 単一の列を取り出す場合、戻り値はSeriesになります。
  • df[[“列名1”, “列名2”, “列名3”]] = 複数の列を取り出す場合はリスト形式となります。戻り値はDataFrameになります。

df["列名1", "列名2", "列名3"]と書きたくなるかもしれませんが、これはエラーとなります。

以下のように理解すると間違えにくくなると思います。

pandas2
Streamlit入門 – 7)Pandasの基礎 8

以下はirisデータセットからspeciesとsepal_length列を取り出して出力する例です。

import seaborn as sns
df = sns.load_dataset("iris")
print(df[["species", "sepal_length"]].head(3))

取り出した2列もデータフレームなので.head()メソッドを使うことができます。

出力は以下の通りです。

  species  sepal_length
0  setosa           5.1
1  setosa           4.9
2  setosa           4.7

列の取りうる値

ある列(もしくは行)で取りうる値の一覧をみるには、uniqueメソッドを使用します。

import seaborn as sns
df = sns.load_dataset("iris")
print(df["species"].unique())

出力は以下の通りです。species(種類)の列で取りうる3つの値が出力されます。

['setosa' 'versicolor' 'virginica']

条件を使った行の抽出

Pandasでは、「特定の列に注目して、その列が特定の条件を満たした場合、その条件を満たす行を取り出す」という処理を頻繁に行うことになります。例えば以下のような場合です。

  • gender列の値がfemaleの行を抽出する
  • age列の値が20未満の行を抽出する
  • score列の値が90以上の行を抽出する

DataFrameではこれらの作業を行う場合、以下のように記述します。

df[条件]

条件は特定の列を取り出して、何等かの値と比較をおこないます。つまり

df[ df[列] 条件比較 ]

という記述になります。

先ほどの例をコードにすると以下のようになります。

  • df[ df[“gender”] == “female” ]
  • df[ df[“age”] < 20 ]
  • df[ df[“score”] >= 90 ]

以下はsepal_lengthが7.6より大きい行だけを抽出するサンプルです。

import seaborn as sns
df = sns.load_dataset("iris")
print(df[df["sepal_length"] > 7.6])

出力は以下の通りです。

     sepal_length  sepal_width  petal_length  petal_width    species
117           7.7          3.8           6.7          2.2  virginica
118           7.7          2.6           6.9          2.3  virginica
122           7.7          2.8           6.7          2.0  virginica
131           7.9          3.8           6.4          2.0  virginica
135           7.7          3.0           6.1          2.3  virginica

複数の条件を指定する場合は以下のように記述します。

  • かつ = df[ (条件1) & (条件2) ]
  • もしくは = df[ (条件1) | (条件2) ]

それぞれの条件を()で囲むこと、andやorという演算子ではなく、&や|を使用することに注意してください。

列の追加

DataFrameでは df[列名] と記述することで、特定の列を取り出すことができました。列名に新しい値を指定して、ここに値を代入すると、新しい列を追加することができます。

import seaborn as sns
df = sns.load_dataset("iris")
df["letters"] = "hello"
print(df.head(3))

出力は以下の通りです。

   sepal_length  sepal_width  petal_length  petal_width species letters
0           5.1          3.5           1.4          0.2  setosa   hello
1           4.9          3.0           1.4          0.2  setosa   hello
2           4.7          3.2           1.3          0.2  setosa   hello

全ての行に列が追加されています。

演習

ex-pandas1.py

IRISのデータセットを読込み、サイドバーで選んだ種類のみを含むデータフレームを右側に表示してください。

ex pandas1
Streamlit入門 – 7)Pandasの基礎 9

ex-pandas2.py

IRISのデータセットを読込み、サイドバーで種類speciesを選択し、それぞれの列をexpanderを使ってグラフを描画してください。

ex pandas2
Streamlit入門 – 7)Pandasの基礎 10

ex-pandas3.py

diamondsのデータセットを読込み、スライダバーで選択された範囲にpriceが含まれるデータのみを表示するページを作成してください。

ex pandas3
Streamlit入門 – 7)Pandasの基礎 11

解答例

ex-pandas1.py

import streamlit as st
import seaborn as sns 

df = sns.load_dataset("iris")
species = ['setosa', 'versicolor', 'virginica']

select = st.sidebar.radio("species", species)
st.dataframe(df[df["species"] == select])

ex-pandas2.py

import streamlit as st
import seaborn as sns 

df = sns.load_dataset("iris")
species = ['setosa', 'versicolor', 'virginica']
select = st.sidebar.radio("species", species)

df = df[df["species"] == select]
for col in ['sepal_length', 'sepal_width', 'petal_length', 'petal_width']:
    with st.expander(col):
        st.line_chart(df[col])

ex-pandas3.py

import streamlit as st
import seaborn as sns 

df = sns.load_dataset("diamonds")
price = st.slider("price", value=(300, 6000))
print(price)
df = df[(df["price"] > price[0]) & (df["price"] < price[1])]
st.dataframe(df)