Polarsで「pandasライブラリ活用入門(第2版)」を書いてみました
はじめに
Pythonにおけるデータ分析ライブラリといえばpandasですが、最近Rust言語で書かれた高速データ分析ライブラリpolarsというライブラリへの注目が集まっています。
今年はQiitaのアドベントカレンダーも作成されているので、多くの方が気になるライブラリだと言えるでしょう。
私も今年の3月にpandasとpolarsのコード比較記事を執筆しましたが、X(旧Twitter)にて動かないコードがあるとのご指摘を頂きました。
どうやらいくつかの破壊的変更があったようです。
参考書籍の第2版が今年の9月に出版されたので、内容を更新したいと思います。
参考
-
pandasライブラリ活用入門[第2版] データクリーニング/前処理など一連の分析プロセスをマスター!
- pandas単体で完結する第1, 2, 4, 5, 6, 8章のコードを記載します。
- API reference — pandas 2.1.4 documentation
- API reference — Polars documentation
前回記事との違い
-
前回は原著のGitHubに沿ってコードを記載しましたが、今回は書籍の内容に沿ってコードを書いていきます。
書籍を買われた方にとって、より見やすい構成になるかと思います。 -
すべてのコードブロックに
import pandas/polars
を記入するので、pandasとpolarsの句は分けないことにします。 -
DataFrame
の表示では、print
ではなくdisplay
を使います。
ライブラリ
pandas 2.1.4
polars 0.19.19
numpy 1.26.2
seaborn 0.13.0
第1部 基本的な使い方
第1章 DataFrame
1.2 最初のデータセットをロードする
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
display("DataFrameの型", type(df))
display("DataFrameの(行数, 列数)", df.shape)
display("DataFrameの列名", df.columns)
display("各列のデータ型", df.dtypes)
display("DataFrameの基本情報", df.info())
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
display("DataFrameの型", type(df))
display("DataFrameの(行数, 列数)", df.shape)
display("DataFrameの列名", df.columns)
display("各列のデータ型", df.dtypes)
display("DataFrameの基本情報", df.describe().transpose(include_header = True))
1.3 列、行、セルを見る
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
display("先頭の5行を表示する", df.head())
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
display("先頭の5行を表示する", df.head())
1.3.1 名前で列を絞り込む
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
country_df = df["country"]
display("最初の5個の値を表示する", country_df.head())
display("最後の5個の値を表示する", country_df.tail())
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
country_df = df["country"]
display("最初の5個の値を表示する", country_df.head(n = 5))
display("最後の5個の値を表示する", country_df.tail(n = 5))
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
subset = df[["country", "continent", "year"]]
display("国と大陸と年を見る", subset)
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
subset = df[["country", "continent", "year"]]
display("国と大陸と年を見る", subset)
1.3.1.1 1個の値で返されるDataFrameやSeries
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
country_df = df["country"]
display("[] で国の列を抽出した場合", country_df.head())
display("データ型", type(country_df))
country_df_list = df[["country"]]
display("[[]] で国の列を抽出した場合", country_df_list.head())
display("データ型", type(country_df_list))
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
country_df = df["country"]
display("[] で国の列を抽出した場合", country_df.head(n = 5))
display("データ型", type(country_df))
country_df_list = df[["country"]]
display("[[]] で国の列を抽出した場合", country_df_list.head())
display("データ型", type(country_df_list))
1.3.2 複数行の抽出
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
display("最初の行を取る", df.loc[0])
last_row_index = df.shape[0] - 1
display("最後の行を取る", df.loc[last_row_index])
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
display("最初の行を取る", df.slice( offset = 0, length = 1))
last_row_index = df.shape[0] - 1
display("最後の行を取る", df.slice( offset = last_row_index, length = 1))
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
display("locで最初の行を取得した場合の型", type(df.loc[0]))
display("head()で最初の行を取得した場合の型", type(df.head(n = 1)))
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
display("sliceで最初の行を取得した場合の型", type(df.slice( offset = 0, length = 1)))
display("head()で最初の行を取得した場合の型", type(df.head(n = 1)))
1.3.2.2 複数行の抽出
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
display("複数行を抽出する", df.loc[[0, 99, 999]])
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
display("複数行を抽出する", df[ [0, 99, 999] ])
1.3.3 行番号による複数行の抽出: iloc[]
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
display("2番目の行を見る", df.iloc[1])
display("100番目の行を見る", df.iloc[99])
display("-1 を使って最後の行を見る", df.iloc[-1])
display("第1行と第100行と第1000行を選択する", df.iloc[[0, 99, 999]])
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
display("2番目の行を見る", df[ 1 ])
display("100番目の行を見る", df[ 99 ])
display("-1 を使って最後の行を見る", df[ -1 ])
display("第1行と第100行と第1000行を選択する", df[ [0, 99, 999] ])
1.3.4 組み合わせで絞り込む
1.3.4.1 複数列の抽出
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
display("locと列名で列を絞り込む", df.loc[:, ["year", "pop"]].head(n = 2))
display("ilocと列番号で列を絞り込む", df.iloc[:, [2, 4, -1]].head(n = 2))
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
display("[]と列名で列を絞り込む", df[:, ["year", "pop"]].head(n = 2))
display("[]と列番号で列を絞り込む", df[:, [2, 4, -1]].head(n = 2))
1.3.4.2 範囲による複数列の抽出
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
display("第0列から第4列までを絞り込む", df.iloc[:, list(range(5))].head(n = 2))
display("第3列から第5列までを絞り込む", df.iloc[:, list(range(3, 6))].head(n = 2))
display("第0列から第5列まで1つおきに絞り込む", df.iloc[:, list(range(0, 6, 2))].head(n = 2))
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
display("第0列から第4列までを絞り込む", df[:, list(range(5))].head(n = 2))
display("第3列から第5列までを絞り込む", df[:, list(range(3, 6))].head(n = 2))
display("第0列から第5列まで1つおきに絞り込む", df[:, list(range(0, 6, 2))].head(n = 2))
1.3.4.3 スライスによる複数列の絞り込み
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
display("最初の3列を絞り込む", df.iloc[:, list(range(3))].head(n = 2))
display("最初の3列をスライス", df.iloc[:, :3].head(n = 2))
display("第3列から第5列までを絞り込む", df.iloc[:, list(range(3, 6))].head(n = 2))
display("第3列から第5列までをスライス", df.iloc[:, 3:6].head(n = 2))
display("第0列から第5列まで1つおきに絞り込む", df.iloc[:, list(range(0, 6, 2))].head(n = 2))
display("第0列から第5列まで1つおきにスライス", df.iloc[:, 0:6:2].head(n = 2))
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
display("最初の3列を絞り込む", df[:, list(range(5))].head(n = 2))
display("最初の3列をスライス", df[:, :3].head(n = 2))
display("第3列から第5列までを絞り込む", df[:, list(range(3, 6))].head(n = 2))
display("第3列から第5列までをスライス", df[:, 3:6].head(n = 2))
display("第0列から第5列まで1つおきに絞り込む", df[:, list(range(0, 6, 2))].head(n = 2))
display("第0列から第5列まで1つおきにスライス", df[:, 0:6:2].head(n = 2))
1.3.5 列と行の抽出
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
display("locを用いて、第43行のcountry列の要素を抽出する", df.loc[42, "country"])
display("ilocを用いて、第43行の第0列の要素を抽出する", df.iloc[42, 0])
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
display("第43行のcountry列の要素を抽出する", df[42, "country"])
display("第43行の第0列の要素を抽出する", df[42, 0])
1.3.5.1 複数行、複数列の抽出
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
display("第1行、第100行、第1000行を、第1列、第4列、第6列から切り出す", df.iloc[[0, 99, 999], [0, 3, 5]])
display("先の抽出を、列名で実行する場合", df.loc[[0, 99, 999], ["country", "lifeExp", "gdpPercap"]])
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
display("第1行、第100行、第1000行を、第1列、第4列、第6列から切り出す", df[[0, 99, 999], [0, 3, 5]])
display("先の抽出を、列名で実行する場合", df[[0, 99, 999], ["country", "lifeExp", "gdpPercap"]])
1.4 グループ分けと集約の計算
疑問
- 各年度で予期された余命(
lifeExp
)の平均値は、いくつなのだろうか。人口(pop
)やGDP(gdpPercap
)の平均値も知りたい - データを大陸(
continent
)ごとに分け、それぞれに同じ計算を実行したら、どういう結果になるか。 - それぞれの大陸のリストに、どれだけの国(
country
)が入っているか。
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
display("グループ分けの前にデータを眺めてみる", df)
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
display("グループ分けの前にデータを眺めてみる", df)
1.4.1 グループごとの平均値
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
# 各年度で予想された余命の平均値は?
# この疑問に答えるには、
# 1. まずデータを年度によって分割し、
# 2. 毎年の"lifeExp"列を取り出し、
# 3. その平均値を計算する
display("各年度で予想された余命の平均値", df.groupby("year")["lifeExp"].mean())
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
# 各年度で予想された余命の平均値は?
# この疑問に答えるには、
# 1. まずデータを年度によって分割し、
# 2. 毎年の"lifeExp"列を取り出し、
# 3. その平均値を計算する
display("各年度で予想された余命の平均値", df.group_by("year").agg( pl.col("lifeExp").mean() ).sort(by = "year"))
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
# 各年度、大陸別の予想された余命の平均値は?
display("各年度、大陸別で予想された余命の平均値",
df\
.groupby(["year", "continent"])[["lifeExp", "gdpPercap"]]\
.mean())
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
# 各年度、大陸別の予想された余命の平均値は?
display("各年度、大陸別で予想された余命の平均値",
df\
.group_by(["year", "continent"])\
.agg([ pl.col("lifeExp").mean(), pl.mean("gdpPercap")])\
.sort(by = "year"))
1.4.2 グループごとの度数/頻度
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
display("各大陸に入っている国の数", df.groupby("continent")["country"].nunique())
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
display("各大陸に入っている国の数",
df\
.group_by(by = "continent")\
.agg( pl.col("country").n_unique() )\
.sort(by = "continent"))
第2章 pandasのデータ構造
2.1 データを自作する
2.1.1 Seriesを作る
import pandas as pd
s = pd.Series(["banana", 42])
display("Seriesを作る", s)
import polars as pl
s = pl.Series(name = None, values = ["banana", 42])
display("Seriesを作る", s)
2.1.2 DataFrameを作る
import pandas as pd
scientists = pd.DataFrame({
"Name": ["Rosaline Franklin", "William Gosset"],
"Occupation": ["Chemist", "Statistician"],
"Born": ["1920-07-25", "1876-06-13"],
"Died": ["1958-04-16", "1937-10-16"]
})
display("DataFrameは辞書型として作るのが最も一般的である", scientists)
import polars as pl
scientists = pl.DataFrame({
"Name": ["Rosaline Franklin", "William Gosset"],
"Occupation": ["Chemist", "Statistician"],
"Born": ["1920-07-25", "1876-06-13"],
"Died": ["1958-04-16", "1937-10-16"]
})
display("DataFrameは辞書型として作るのが最も一般的である", scientists)
# indexはpandasのみ
import pandas as pd
scientists = pd.DataFrame({
"Occupation": ["Chemist", "Statistician"],
"Born": ["1920-07-25", "1876-06-13"],
"Died": ["1958-04-16", "1937-10-16"],
"Age": [37, 61]
},
index = ["Rosaline Franklin", "William Gosset"],
columns = ["Occupation", "Born", "Died", "Age"])
display("Index付きDataFrameはpandasのみ", scientists)
# polarsのDataFrame作成に関するtips
import polars as pl
data = {
"Name": ["Rosaline Franklin", "William Gosset"],
"Occupation": ["Chemist", "Statistician"],
"Born": ["1920-07-25", "1876-06-13"],
"Died": ["1958-04-16", "1937-10-16"],
"Age": [37, 61]
}
scientists = pl.DataFrame(data = data, schema = {
"Name": pl.Utf8,
"Occupation": pl.Utf8,
"Born": pl.Date,
"Died": pl.Date,
"Age": pl.Int64
})
scientists
display("polarsでDataFrame作成時に各列のデータ型を指定したい場合、辞書型を使用する(その1)", scientists)
scientists = pl.DataFrame(data = data, schema = [
("Name", pl.Utf8),
("Occupation", pl.Utf8),
("Born", pl.Date),
("Died", pl.Date),
("Age", pl.Int64)
])
display("tupleのlistでも各列のデータ型を指定できる(その2)", scientists)
data = [
pl.Series("Name", ["Rosaline Franklin", "William Gosset"], dtype = pl.Utf8),
pl.Series("Occupation", ["Chemist", "Statistician"], dtype = pl.Utf8),
pl.Series("Born", ["1920-07-25", "1876-06-13"], dtype = pl.Date),
pl.Series("Died", ["1958-04-16", "1937-10-16"], dtype = pl.Date),
pl.Series("Age", [37, 61], dtype = pl.Int64)
]
scientists = pl.DataFrame(data = data)
display("SeriesのリストとしてDataFrameを定義する", scientists)
2.2 Seriesについて
import pandas as pd
scientists = pd.DataFrame({
"Occupation": ["Chemist", "Statistician"],
"Born": ["1920-07-25", "1876-06-13"],
"Died": ["1958-04-16", "1937-10-16"],
"Age": [37, 61]
},
index = ["Rosaline Franklin", "William Gosset"],
columns = ["Occupation", "Born", "Died", "Age"])
display("DataFrameの再表示", scientists)
first_row = scientists.loc["William Gosset"]
display("indexがWilliam Gossetの行(第2行)のデータ型", type(first_row))
display("William Gosset行のindex", first_row.index)
display("William Gosset行の各要素", first_row.values)
display("William Gosset行の各キー", first_row.keys())
display("William Gosset行のindexの最初の要素", first_row.index[0])
display("William Gosset行の各キーの最初の要素", first_row.keys()[0])
import polars as pl
data = [
pl.Series("Name", ["Rosaline Franklin", "William Gosset"], dtype = pl.Utf8),
pl.Series("Occupation", ["Chemist", "Statistician"], dtype = pl.Utf8),
pl.Series("Born", ["1920-07-25", "1876-06-13"], dtype = pl.Date),
pl.Series("Died", ["1958-04-16", "1937-10-16"], dtype = pl.Date),
pl.Series("Age", [37, 61], dtype = pl.Int64)
]
scientists = pl.DataFrame(data = data)
display("DataFrameの再表示", scientists)
# polarsにはindexがないので、filterで取得する
first_row = scientists.filter( pl.col("Name") == "William Gosset" )
display("indexがWilliam Gossetの行(第2行)のデータ型", type(first_row))
# polarsのkey関係はよくわからなかった
#display("William Gosset行のindex", first_row.index)
#display("William Gosset行の各要素", first_row.values)
#display("William Gosset行の各キー", first_row.keys())
#display("William Gosset行のindexの最初の要素", first_row.index[0])
#display("William Gosset行の各キーの最初の要素", first_row.keys()[0])
2.2.1 Seriesは、ndarrayに似たもの
2.2.1.1 Seriesのメソッド
import pandas as pd
scientists = pd.DataFrame({
"Occupation": ["Chemist", "Statistician"],
"Born": ["1920-07-25", "1876-06-13"],
"Died": ["1958-04-16", "1937-10-16"],
"Age": [37, 61]
},
index = ["Rosaline Franklin", "William Gosset"],
columns = ["Occupation", "Born", "Died", "Age"])
ages = scientists["Age"]
display("Age列", ages)
print("Age列の平均値\n", ages.mean(), "\n")
print("最小値\n", ages.min(), "\n")
print("最大値\n", ages.max(), "\n")
print("標準偏差\n", ages.std(), "\n")
import polars as pl
data = [
pl.Series("Name", ["Rosaline Franklin", "William Gosset"], dtype = pl.Utf8),
pl.Series("Occupation", ["Chemist", "Statistician"], dtype = pl.Utf8),
pl.Series("Born", ["1920-07-25", "1876-06-13"], dtype = pl.Date),
pl.Series("Died", ["1958-04-16", "1937-10-16"], dtype = pl.Date),
pl.Series("Age", [37, 61], dtype = pl.Int64)
]
ages = scientists["Age"]
display("Age列", ages)
print("Age列の平均値\n", ages.mean(), "\n")
print("最小値\n", ages.min(), "\n")
print("最大値\n", ages.max(), "\n")
print("標準偏差\n", ages.std(), "\n")
import pandas as pd
# 初心者でもわかる!やさしい統計用語①「相関関係」 | データで越境者に寄り添うメディア データのじかん
# https://data.wingarc.com/statistics-for-beginners-01-46546
s1 = pd.Series([20, 21, 30, 25, 27, 33, 25, 26, 27, 28])
s2 = pd.Series([20, 32, 50, 30, 56, 62, 50, 47, 25, 36])
display("気温", s1)
display("アイスの販売数量", s2)
print("気温とアイスの販売数量の相関係数\n", s1.corr(s2), "\n")
print("気温とアイスの販売数量の共分散\n", s1.cov(s2), "\n")
display("気温の要約統計量", s1.describe())
display("気温列から重複のない要素を返す", s1.drop_duplicates())
print("気温と販売数量で同じ要素を含んでいるかを確認する\n", s1.equals(s2), "\n")
print("気温の最小値\n", s1.min(), "\n")
print("気温の最大値\n", s1.max(), "\n")
print("気温の算術平均\n", s1.mean(), "\n")
print("気温の中央値\n", s1.median(), "\n")
print("気温の最頻値\n", s1.mode(), "\n")
print("気温の第1四分位数\n", s1.quantile(q = 0.25), "\n")
display("気温列の値を1つ指定して、もう一つの指定値で上書きする", s1.replace(to_replace = {33: 9000}))
display("いくつかの要素を抽出する", s1.sample(n = 3, random_state = 42))
display("ソートする", s1.sort_values())
display("DataFrameに変換する", s1.to_frame())
display("転置する", s1.transpose())
display("ユニーク値を返す", s1.unique())
import polars as pl
# 初心者でもわかる!やさしい統計用語①「相関関係」 | データで越境者に寄り添うメディア データのじかん
# https://data.wingarc.com/statistics-for-beginners-01-46546
s1 = pl.Series("Temperature", [20, 21, 30, 25, 27, 33, 25, 26, 27, 28])
s2 = pl.Series("Number of units sold", [20, 32, 50, 30, 56, 62, 50, 47, 25, 36])
df = pl.DataFrame([
s1,
s2
])
display("気温", s1)
display("アイスの販売数量", s2)
display("気温とアイスの販売数量の相関係数", df.select(pl.corr("Temperature", "Number of units sold")))
display("気温とアイスの販売数量の共分散", df.select(pl.cov("Temperature", "Number of units sold")))
display("気温の要約統計量", s1.describe())
#display("気温列から重複のない要素を返す", s1.drop_duplicates())
print("気温と販売数量で同じ要素を含んでいるかを確認する\n", s1.equals(s2), "\n")
print("気温の最小値\n", s1.min(), "\n")
print("気温の最大値\n", s1.max(), "\n")
print("気温の算術平均\n", s1.mean(), "\n")
print("気温の中央値\n", s1.median(), "\n")
print("気温の最頻値\n", s1.mode(), "\n")
print("気温の第1四分位数\n", s1.quantile(quantile = 0.25), "\n")
display("気温列の値を1つ指定して、もう一つの指定値で上書きする", s1.replace(mapping = {33: 9000}))
display("いくつかの要素を抽出する", s1.sample(n = 3, seed = 42))
display("ソートする", s1.sort())
display("DataFrameに変換する", s1.to_frame())
#display("転置する", s1.transpose())
display("ユニーク値を返す", s1.unique())
2.2.2 Seriesを真偽値で絞り込む
ローカルフォルダに保存したデータを読み込むときは、下図のようなフォルダ構造を想定しています。
import pandas as pd
scientists = pd.read_csv("../data/scientists.csv")
display("読み込んだデータを確認する", scientists)
ages = scientists["Age"]
display("年齢列", ages)
display("要約統計量", ages.describe())
print("要約統計量\n", ages.mean(), "\n")
display("平均より高い値だけ絞り込む", ages[ages > ages.mean()])
print("絞り込みのデータ型\n", type(ages > ages.mean()), "\n")
import polars as pl
scientists = pl.read_csv("../data/scientists.csv")
display("読み込んだデータを確認する", scientists)
ages = scientists["Age"]
display("年齢列", ages)
display("要約統計量", ages.describe())
print("要約統計量\n", ages.mean(), "\n")
display("平均より高い値だけ絞り込む", ages.filter( ages > ages.mean() ))
print("絞り込みのデータ型\n", type(ages > ages.mean()), "\n")
2.2.3 演算の自動的な整列とベクトル化(ブロードキャスティング)
2.2.3.1 同じ長さのベクトル
import pandas as pd
scientists = pd.read_csv("../data/scientists.csv")
ages = scientists["Age"]
display("ベクトルの和", ages + ages)
display("アダマール積", ages + ages)
import polars as pl
scientists = pl.read_csv("../data/scientists.csv")
ages = scientists["Age"]
display("ベクトルの和", ages + ages)
display("アダマール積", ages + ages)
2.2.3.2 ベクトルと整数値(スカラー)
import pandas as pd
scientists = pd.read_csv("../data/scientists.csv")
ages = scientists["Age"]
display("ベクトルの全ての要素にスカラーを加える", ages + 100)
display("ベクトルとスカラーの積", ages * 2)
import polars as pl
scientists = pl.read_csv("../data/scientists.csv")
ages = scientists["Age"]
display("ベクトルの全ての要素にスカラーを加える", ages + 100)
display("ベクトルとスカラーの積", ages * 2)
2.3 DataFrameについて
2.3.1 DataFrameの構成要素
import pandas as pd
scientists = pd.read_csv("../data/scientists.csv")
display("index列を取り出す", scientists.index)
display("列名", scientists.columns)
display("要素", scientists.values)
#display("arrow形式", scientists.to_arrow())
#display("辞書型", scientists.to_dicts())
import polars as pl
scientists = pl.read_csv("../data/scientists.csv")
#display("index列を取り出す", scientists.index)
display("列名", scientists.columns)
display("要素", scientists.to_numpy())
display("arrow形式", scientists.to_arrow())
display("辞書型", scientists.to_dicts())
2.3.2 DataFrameを真偽値で絞り込む
import pandas as pd
scientists = pd.read_csv("../data/scientists.csv")
display("真偽値で絞り込む", scientists.loc[ scientists["Age"] > scientists["Age"].mean() ])
import polars as pl
scientists = pl.read_csv("../data/scientists.csv")
display("真偽値で絞り込む", scientists.filter( scientists["Age"] > scientists["Age"].mean() ).sort("Name"))
display("マイナーチェンジ 1", scientists.filter( pl.col("Age") > scientists["Age"].mean() ).sort("Name"))
display("マイナーチェンジ 2", scientists.filter( scientists["Age"] > pl.col("Age").mean() ).sort("Name"))
display("マイナーチェンジ 3", scientists.filter( pl.col("Age") > pl.col("Age").mean() ).sort("Name"))
display("マイナーチェンジ 4", scientists.filter( pl.col("Age") > pl.mean("Age") ).sort("Name"))
2.4 SeriesとDataFrameの書き換え
import pandas as pd
scientists = pd.read_csv("../data/scientists.csv")
display("各列のデータ型", scientists.dtypes)
born_datetime = pd.to_datetime(scientists["Born"], format = "%Y-%m-%d")
display("生年月日のDateTime型", born_datetime)
died_datetime = pd.to_datetime(scientists["Died"], format = "%Y-%m-%d")
display("死亡日のDateTime型", died_datetime)
scientists["born_dt"], scientists["died_dt"] = (
born_datetime,
died_datetime
)
display("列追加後のDataFrame", scientists)
import polars as pl
scientists = pl.read_csv("../data/scientists.csv")
display("各列のデータ型", scientists.dtypes)
born_datetime = scientists["Born"].str.to_date(format = "%Y-%m-%d")
display("生年月日のDateTime型", born_datetime)
died_datetime = scientists["Died"].str.to_date(format = "%Y-%m-%d")
display("死亡日のDateTime型", died_datetime)
scientists = scientists.with_columns([
born_datetime.alias("born_dt"),
died_datetime.alias("died_dt")
])
display("列追加後のDataFrame", scientists)
2.4.2 列を直接変更する
import pandas as pd
import numpy as np
scientists = pd.read_csv("../data/scientists.csv")
scientists["born_dt"], scientists["died_dt"] = (
pd.to_datetime(scientists["Born"], format = "%Y-%m-%d"),
pd.to_datetime(scientists["Died"], format = "%Y-%m-%d")
)
scientists["age_days"] = (
scientists["died_dt"] - scientists["born_dt"]
)
scientists["age_years"] = (
scientists["age_days"] / np.timedelta64(1, "ns") / (365.2425 * 24 * 60 * 60 * 1e9)
)
display("生年月日から死亡日までの年数を追加したDataFrame", scientists)
import polars as pl
scientists = pl.read_csv("../data/scientists.csv")
scientists = scientists.with_columns([
scientists["Born"].str.to_date(format = "%Y-%m-%d").alias("born_dt"),
scientists["Died"].str.to_date(format = "%Y-%m-%d").alias("died_dt")
])
scientists = scientists.with_columns([
(scientists["died_dt"] - scientists["born_dt"]).alias("age_days")
])
scientists = scientists.with_columns([
(scientists["age_days"].dt.days() / 365.0 ).alias("age_years")
])
display("列追加後のDataFrame", scientists)
2.4.4 値を捨てる
import pandas as pd
scientists = pd.read_csv("../data/scientists.csv")
print("元のデータの列名\n", scientists.columns, "\n")
scientists_dropped = scientists.drop(["Age"], axis = "columns")
print("Age列削除後のデータの列名\n", scientists_dropped.columns, "\n")
import polars as pl
import numpy as np
scientists = pl.read_csv("../data/scientists.csv")
print("元のデータの列名\n", scientists.columns, "\n")
scientists_dropped = scientists.drop(["Age"])
print("Age列削除後のデータの列名\n", scientists_dropped.columns, "\n")
2.5 データのエクスポートとインポート
2.5.1 pickle
polarsにはpickle形式での保存方法は無い
2.5.1.1 Series
2.5.1.2 DataFrame
2.5.1.3 pickleデータを読み込む
2.5.2 CSV
import pandas as pd
import numpy as np
scientists = pd.read_csv("../data/scientists.csv")
scientists["born_dt"], scientists["died_dt"] = (
pd.to_datetime(scientists["Born"], format = "%Y-%m-%d"),
pd.to_datetime(scientists["Died"], format = "%Y-%m-%d")
)
scientists["age_days"] = (
scientists["died_dt"] - scientists["born_dt"]
)
scientists["age_years"] = (
scientists["age_days"] / np.timedelta64(1, "ns") / (365.2425 * 24 * 60 * 60 * 1e9)
)
scientists.to_csv("../output/scientists_df_no_index.csv", index = False)
import polars as pl
scientists = pl.read_csv("../data/scientists.csv")
scientists = scientists.with_columns([
scientists["Born"].str.to_date(format = "%Y-%m-%d").alias("born_dt"),
scientists["Died"].str.to_date(format = "%Y-%m-%d").alias("died_dt")
])
scientists = scientists.with_columns([
(scientists["died_dt"] - scientists["born_dt"]).alias("age_days")
])
scientists = scientists.with_columns([
(scientists["age_days"].dt.days() / 365.0 ).alias("age_years")
])
display("age_daysの値が13779dでありCSV保存の時にエラーが出る", scientists["age_days"].head(2))
scientists = scientists.replace(
"age_days", scientists["age_days"].dt.days()
)
display("age_daysの値を整数型に変換する", scientists["age_days"].head(2))
scientists.write_csv("../output/scientists_df.csv")
2.5.3 Excel
import pandas as pd
import numpy as np
scientists = pd.read_csv("../data/scientists.csv")
scientists["born_dt"], scientists["died_dt"] = (
pd.to_datetime(scientists["Born"], format = "%Y-%m-%d"),
pd.to_datetime(scientists["Died"], format = "%Y-%m-%d")
)
scientists["age_days"] = (
scientists["died_dt"] - scientists["born_dt"]
)
scientists["age_years"] = (
scientists["age_days"] / np.timedelta64(1, "ns") / (365.2425 * 24 * 60 * 60 * 1e9)
)
scientists.to_excel("../output/scientists_df_no_index.xlsx", index = False)
import polars as pl
scientists = pl.read_csv("../data/scientists.csv")
scientists = scientists.with_columns([
scientists["Born"].str.to_date(format = "%Y-%m-%d").alias("born_dt"),
scientists["Died"].str.to_date(format = "%Y-%m-%d").alias("died_dt")
])
scientists = scientists.with_columns([
(scientists["died_dt"] - scientists["born_dt"]).alias("age_days")
])
scientists = scientists.with_columns([
(scientists["age_days"].dt.days() / 365.0 ).alias("age_years")
])
'''
display("age_daysの値が13779dでありCSV保存の時にエラーが出る", scientists["age_days"].head(2))
scientists = scientists.replace(
"age_days", scientists["age_days"].dt.days()
)
display("age_daysの値を整数型に変換する", scientists["age_days"].head(2))
'''
scientists.write_excel("../output/scientists_df.xlsx")
第4章 「整然データ」を作る
4.1 列に(変数ではなく)値が入っているとき
4.1.1 1列に集める
import pandas as pd
pew = pd.read_csv("../data/pew.csv")
display("最初の5列を表示する", pew.iloc[:, 0:5])
pew_long = pew.melt(id_vars = "religion", var_name = "income", value_name = "count")
display("縦持ちデータを表示する", pew_long)
import polars as pl
pew = pl.read_csv("../data/pew.csv")
display("最初の5列を表示する", pew[:, 0:5])
pew_long = pew.melt(id_vars = "religion", variable_name = "income", value_name = "count")
display("縦持ちデータを表示する", pew_long)
4.1.2 複数の列を残す
import pandas as pd
billboard = pd.read_csv("../data/billboard.csv")
display("列および行の先頭部分を表示する", billboard.iloc[0:5, 0:16])
billboard_long = billboard\
.melt(id_vars = ["year", "artist", "track", "time", "date.entered"],
var_name = "week",
value_name = "rating")
display("縦持ちデータを表示する", billboard_long)
import polars as pl
billboard = pl.read_csv("../data/billboard.csv")
display("列および行の先頭部分を表示する", billboard[0:5, 0:16])
billboard_long = billboard\
.melt(id_vars = ["year", "artist", "track", "time", "date.entered"],
variable_name = "week",
value_name = "rating")
display("縦持ちデータを表示する", billboard_long)
4.2 複数の変数を含む列があるとき
import pandas as pd
ebola = pd.read_csv("../data/country_timeseries.csv")
display("先頭のデータを表示する", ebola.head(n = 3))
ebola_long = ebola.melt(id_vars = ["Date", "Day"])
display("縦持ちデータを表示する", ebola_long.head(n = 3))
import polars as pl
ebola = pl.read_csv("../data/country_timeseries.csv")
display("先頭のデータを表示する", ebola.head(n = 3))
ebola_long = ebola.melt(id_vars = ["Date", "Day"])
display("縦持ちデータを表示する", ebola_long.head(n = 3))
4.2.1 列を分解して個別に追加する
import pandas as pd
ebola = pd.read_csv("../data/country_timeseries.csv")
ebola_long = ebola.melt(id_vars = ["Date", "Day"])
variable_split = ebola_long["variable"].str.split("_")
display("発症_国名のデータを分割する", variable_split.head(n = 3))
print("分割した列のデータ型", type(variable_split), "\n")
print("分割した列の最初の要素のデータ型", type(variable_split[0]), "\n")
status_values = variable_split.str.get(0)
country_values = variable_split.str.get(1)
ebola_long["status"] = status_values
ebola_long["country"] = country_values
display("分割した列を縦持ちデータに追加する", ebola_long)
import polars as pl
ebola = pl.read_csv("../data/country_timeseries.csv")
ebola_long = ebola.melt(id_vars = ["Date", "Day"])
variable_split = ebola_long["variable"].str.split("_")
display("発症_国名のデータを分割する", variable_split.head(n = 3))
print("分割した列のデータ型", type(variable_split), "\n")
print("分割した列の最初の要素のデータ型", type(variable_split[0]), "\n")
df_variable_split = ebola_long["variable"]\
.str.split_exact("_", 1)\
.struct.rename_fields(["status", "country"])\
.alias("fields")\
.to_frame().unnest("fields")
status_values = df_variable_split["status"]
country_values = df_variable_split["country"]
ebola_long = ebola_long.with_columns([
status_values,
country_values
])
display("分割した列を縦持ちデータに追加する", ebola_long)
4.2.2 分割と結合を一度に行う
import pandas as pd
ebola = pd.read_csv("../data/country_timeseries.csv")
ebola_long = ebola.melt(id_vars = ["Date", "Day"])
variable_split = ebola_long.variable.str.split("_", expand = True)
ebola_long[ ["status", "country"] ] = variable_split
display("分割した列を縦持ちデータに追加する", ebola_long.head(n = 3))
import polars as pl
ebola = pl.read_csv("../data/country_timeseries.csv")
#polarsで同様のことを行う場合 その1
#Series表記の場合、to_fram()とunnest()メソッドが必要
ebola_long = ebola.melt(id_vars = ["Date", "Day"])
ebola_long = ebola_long.with_columns(
ebola_long["variable"]\
.str.split_exact("_", 1)\
.struct.rename_fields(["status", "country"])\
.alias("fields")\
.to_frame()\
.unnest("fields")
)
display("分割した列を縦持ちデータに追加する", ebola_long.head(n = 3))
import polars as pl
ebola = pl.read_csv("../data/country_timeseries.csv")
#polarsで同様のことを行う場合 その2
#pl.cpl()を用いる場合、unnestは最後につける
ebola_long = ebola.melt(id_vars = ["Date", "Day"])
ebola_long = ebola_long.with_columns(
pl.col("variable")\
.str.split_exact("_", 1)\
.struct.rename_fields(["status", "country"])\
.alias("fields")
).unnest("fields")
display("分割した列を縦持ちデータに追加する", ebola_long.head(n = 3))
4.3 行と列の両方に変数があるとき
import pandas as pd
weather = pd.read_csv("../data/weather.csv")
display("元のデータの表示", weather.head(n = 3))
weather_melt = weather.melt(
id_vars = ["id", "year", "month", "element"],
var_name = "day",
value_name = "temp"
)
display("縦持ちデータの表示", weather_melt.head(n = 3))
weather_tidy = weather_melt.pivot(
index = ["id", "year", "month", "day"],
columns = "element",
values = "temp"
)
display("気温の最大値・最小値をピボット展開したデータの表示", weather_tidy.head(n = 3))
#pandasで層別indexを分解したい場合
#weather_tidy_flat = weather_tidy.reset_index()
import polars as pl
weather = pl.read_csv("../data/weather.csv")
display("元のデータの表示", weather.head(n = 3))
weather_melt = weather.melt(
id_vars = ["id", "year", "month", "element"],
variable_name = "day",
value_name = "temp"
)
display("縦持ちデータの表示", weather_melt.head(n = 3))
weather_tidy = weather_melt.pivot(
index = ["id", "year", "month", "day"],
columns = "element",
values = "temp"
)
display("気温の最大値・最小値をピボット展開したデータの表示", weather_tidy.head(n = 3))
import pandas as pd
weather = pd.read_csv("../data/weather.csv")
weather_melt = weather.melt(
id_vars = ["id", "year", "month", "element"],
var_name = "day",
value_name = "temp"
)
# 先ほどのmelt, pivotをメソッドチェーンで記述する
# データ処理の方向性が決まったら、処理の一連をチェーンする形で書き直すのが良いだろう
weather_tidy = (
weather_melt\
.pivot(index = ["id", "year", "month", "day"],
columns = "element",
values = "temp")\
.reset_index()
)
display("気温の最大値・最小値をピボット展開したデータの表示", weather_tidy.head(n = 3))
import polars as pl
weather = pl.read_csv("../data/weather.csv")
weather_melt = weather.melt(
id_vars = ["id", "year", "month", "element"],
variable_name = "day",
value_name = "temp"
)
# 先ほどのmelt, pivotをメソッドチェーンで記述する
# データ処理の方向性が決まったら、処理の一連をチェーンする形で書き直すのが良いだろう
weather_tidy = weather.melt(
id_vars = ["id", "year", "month", "element"],
variable_name = "day",
value_name = "temp"
).pivot(
index = ["id", "year", "month", "day"],
columns = "element",
values = "temp"
)
display("気温の最大値・最小値をピボット展開したデータの表示", weather_tidy.head(n = 3))
第5章 関数を適用(apply)する
5.1 関数の初歩
# pandas, polarsは使用しないブロック
def my_function():
pass
def my_sq(x):
return x ** 2
def avg_2(x, y):
return (x + y)/ 2
my_calc_1 = my_sq(4)
print(my_calc_1)
my_calc_2 = avg_2(10,20)
print(my_calc_2)
5.2 applyの基本
import pandas as pd
df = pd.DataFrame({
"a": [10, 20, 30],
"b": [20, 30, 40]
})
display("元データ", df["a"])
display("各要素を2乗する", df["a"] ** 2)
import polars as pl
df = pl.DataFrame({
"a": [10, 20, 30],
"b": [20, 30, 40]
})
display("元データ", df["a"])
display("各要素を2乗する", df["a"] ** 2)
5.2.1 関数をSeriesに適用する
import pandas as pd
df = pd.DataFrame({
"a": [10, 20, 30],
"b": [20, 30, 40]
})
print("抽出した列aのデータ型", type(df["a"]))
print("抽出した1行目のデータ型", type(df.iloc[0, :]))
def my_sq(x):
return x ** 2
sq = df["a"].apply(my_sq)
display("Seriesの各要素を2乗したSeries", sq)
def my_exp(x, e):
return x ** e
ex = df["a"].apply(my_exp, e = 3)
display("Seriesの各要素を3乗したSeries", ex)
import polars as pl
df = pl.DataFrame({
"a": [10, 20, 30],
"b": [20, 30, 40]
})
print("抽出した列aのデータ型", type(df["a"]))
print("抽出した1行目のデータ型", type(df[0, :]))
def my_sq(x):
return x ** 2
# polarsのapplyは将来的に削除される
#sq = df["a"].apply(my_sq)
sq = df["a"].map_elements(lambda x: my_sq(x))
display("Seriesの各要素を2乗したSeries", sq)
def my_exp(x, e):
return x ** e
ex = df["a"].map_elements(lambda elemtn: my_exp(x = elemtn, e = 3))
display("Seriesの各要素を3乗したSeries", ex)
5.2.2 関数をDataFrameに適用する
5.2.2.1 列ごとの演算
polarsのapplyやmap_rowsには列ごとの処理が無いようなので、この節は省略
5.2.2.2 行ごとの演算
import pandas as pd
df = pd.DataFrame({
"a": [10, 20, 30],
"b": [20, 30, 40]
})
def avg_2_apply(row):
x = row[0]
y = row[1]
return (x + y)/2
display("行ごとに関数を適用する", df.apply(avg_2_apply, axis = 1))
import polars as pl
df = pl.DataFrame({
"a": [10, 20, 30],
"b": [20, 30, 40]
})
def avg_2_apply(row):
x = row[0]
y = row[1]
return (x + y)/2
#display("行ごとに関数を適用する", df.apply(lambda row: avg_2_apply(row)))
display("行ごとに関数を適用する", df.map_rows(lambda row: avg_2_apply(row)))
5.3 関数のベクトル化
import pandas as pd
df = pd.DataFrame({
"a": [10, 20, 30],
"b": [20, 30, 40]
})
def avg_2(x, y):
return (x + y)/2
display("2つの列をベクトルのように扱う", avg_2(df["a"], df["b"]))
import polars as pl
df = pl.DataFrame({
"a": [10, 20, 30],
"b": [20, 30, 40]
})
def avg_2(x, y):
return (x + y)/2
display("2つの列をベクトルのように扱う", avg_2(df["a"], df["b"]))
#display("別の書き方 その1", df.apply(lambda row: avg_2(row[0], row[1])))
display("別の書き方 その2", df.map_rows(lambda row: avg_2(row[0], row[1])))
第2部 データ操作
第6章 データの組立
6.1 データセットを組み合わせる
6.2 連結
import pandas as pd
df1 = pd.read_csv("../data/concat_1.csv")
df2 = pd.read_csv("../data/concat_2.csv")
df3 = pd.read_csv("../data/concat_3.csv")
display("元データ その1", df1)
display("元データ その2", df2)
display("元データ その3", df3)
import polars as pl
df1 = pl.read_csv("../data/concat_1.csv")
df2 = pl.read_csv("../data/concat_2.csv")
df3 = pl.read_csv("../data/concat_3.csv")
display("元データ その1", df1)
display("元データ その2", df2)
display("元データ その3", df3)
6.2.1 DataFrameの構成要素(復習)
index, columns, valuesなので省略
6.2.2 行の追加
import pandas as pd
df1 = pd.read_csv("../data/concat_1.csv")
df2 = pd.read_csv("../data/concat_2.csv")
df3 = pd.read_csv("../data/concat_3.csv")
row_concat = pd.concat([df1, df2, df3])
display("行方向に結合したデータ(縦結合)", row_concat)
new_row_df = pd.DataFrame({
"A": ["n1"],
"B": ["n2"],
"C": ["n3"],
"D": ["n4"]
})
display("行方向に結合したデータ(縦結合)", pd.concat([df1, new_row_df]))
import polars as pl
df1 = pl.read_csv("../data/concat_1.csv")
df2 = pl.read_csv("../data/concat_2.csv")
df3 = pl.read_csv("../data/concat_3.csv")
row_concat = pl.concat(items = [df1, df2, df3], how = 'vertical')
display("行方向に結合したデータ(縦結合)", row_concat)
new_row_df = pl.DataFrame({
"A": ["n1"],
"B": ["n2"],
"C": ["n3"],
"D": ["n4"]
})
display("行方向に結合したデータ(縦結合)", pl.concat(items = [df1, new_row_df], how = 'vertical'))
6.2.2.1 インデックスの再設定
polarsにはindexが無いので省略
6.2.3 列の追加
import pandas as pd
df1 = pd.read_csv("../data/concat_1.csv")
df2 = pd.read_csv("../data/concat_2.csv")
df3 = pd.read_csv("../data/concat_3.csv")
#polarsでは同じ列名が許されないので、pandasと同様の横結合はできない
col_concat = pd.concat([df1, df2, df3], axis = "columns")
display("列方向に結合したデータ(横結合)", col_concat)
import polars as pl
df1 = pl.read_csv("../data/concat_1.csv")
df2 = pl.read_csv("../data/concat_2.csv")
df3 = pl.read_csv("../data/concat_3.csv")
# polarsで同名の列を横結合する場合、renameする必要がある
col_concat = pl.concat(items = [df1,
df2.rename(mapping = {"A": "A2", "B": "B2", "C": "C2", "D": "D2"}),
df3.rename(mapping = {"A": "A3", "B": "B3", "C": "C3", "D": "D3"})],
how = 'horizontal')
display("列方向に結合したデータ(横結合)", col_concat)
6.2.4 インデックスが異なる連結
6.2.4.1 列に相違のある行を連結する
import pandas as pd
df1 = pd.read_csv("../data/concat_1.csv")
df2 = pd.read_csv("../data/concat_2.csv")
df3 = pd.read_csv("../data/concat_3.csv")
df1.columns = ["A", "B", "C", "D"]
df2.columns = ["E", "F", "G", "H"]
df3.columns = ["A", "C", "F", "H"]
display("元データ その1", df1)
display("列名を変更したデータ その1", df2)
display("列名を変更したデータ その2", df3)
# 列名が異なるDataFrameを盾結合する場合は'diagonal'を指定する
row_concat = pd.concat([df1, df2, df3])
display("行方向に結合したデータ(縦結合)", row_concat)
import polars as pl
df1 = pl.read_csv("../data/concat_1.csv")
df2 = pl.read_csv("../data/concat_2.csv")
df3 = pl.read_csv("../data/concat_3.csv")
df1.columns = ["A", "B", "C", "D"]
df2.columns = ["E", "F", "G", "H"]
df3.columns = ["A", "C", "F", "H"]
display("元データ その1", df1)
display("列名を変更したデータ その1", df2)
display("列名を変更したデータ その2", df3)
# 列名が異なるDataFrameを盾結合する場合は'diagonal'を指定する
row_concat = pl.concat(items = [df1, df2, df3], how = 'diagonal')
display("行方向に結合したデータ(縦結合)", row_concat)
6.2.4.2 行に相違のある列を連結する
polarsにindexは無いので、この節は省略
6.3 データが観測単位ごとの表に分かれている場合
github上に書籍で紹介されているデータがないのでスキップする
第8章 groupby演算による分割-適用-結合
8.1 集約
8.1.1 1この変数で分割する基本的な集約
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
display("元データ", df)
avg_life_by_year = df.groupby(by = "year")["lifeExp"].mean()
display("年度別に平均余命を集計する", avg_life_by_year)
print("記録がある年度の一覧", df["year"].unique())
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
display("元データ", df)
avg_life_by_year = df.group_by(by = "year").agg( pl.col("lifeExp").mean() ).sort(by = "year")
display("年度別に平均余命を集計する", avg_life_by_year)
print("記録がある年度の一覧", df["year"].unique().to_list())
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
y1952 = df[ df["year"] == 1952 ]
display("1952年のデータ", y1952)
y1952_mean = y1952["lifeExp"].mean()
print("1952年の余命平均", y1952_mean)
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
y1952 = df.filter( pl.col("year") == 1952 )
display("1952年のデータ", y1952)
y1952_mean = y1952["lifeExp"].mean()
print("1952年の余命平均", y1952_mean)
8.1.2 組込みの集約メソッド
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
display("年度別の国数", df.groupby(by = "year")["country"].count().head(1) )
display("年度別の人口のカウント", df.groupby(by = "year")["country"].size().head(1) )
display("年度別の人口の平均", df.groupby(by = "year")["pop"].mean().head(1) )
display("年度別の人口の標準偏差", df.groupby(by = "year")["pop"].std().head(1) )
display("年度別の人口の最小値", df.groupby(by = "year")["pop"].min().head(1) )
display("年度別の人口の四分位数", df.groupby(by = "year")["pop"].quantile(q = 0.25).head(1) )
display("年度別の人口中央値", df.groupby(by = "year")["pop"].quantile(q = 0.5).head(1) )
display("年度別の人口第3四分位数", df.groupby(by = "year")["pop"].quantile(q = 0.75).head(1) )
display("年度別の人口最大値", df.groupby(by = "year")["pop"].max().head(1) )
display("年度別の人口の和", df.groupby(by = "year")["pop"].sum().head(1) )
display("年度別の人口の分散", df.groupby(by = "year")["pop"].var().head(1) )
display("年度別の人口の不偏標準偏差", df.groupby(by = "year")["pop"].sem().head(1) )
display("年度別の人口の基本統計量", df.groupby(by = "year")["pop"].describe().head(1) )
display("年度別の人口の最初の要素", df.groupby(by = "year")["pop"].first().head(1) )
display("年度別の人口の最後の要素", df.groupby(by = "year")["pop"].last().head(1) )
display("年度別の第1番の要素", df.groupby(by = "year").nth(1).head(1) )
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
display("年度別の国数", df.group_by(by = "year").agg( pl.col("country").count() ).head(1) )
#display("年度別の人口のカウント", df.group_by(by = "year").agg( pl.col("country").size() ) )
display("年度別の人口の平均", df.group_by(by = "year").agg( pl.col("pop").mean() ).head(1) )
display("年度別の人口の標準偏差", df.group_by(by = "year").agg( pl.col("pop").std() ).head(1) )
display("年度別の人口の最小値", df.group_by(by = "year").agg( pl.col("pop").min() ).head(1) )
display("年度別の人口の四分位数", df.group_by(by = "year").agg( pl.col("pop").quantile(quantile = 0.25) ).head(1) )
display("年度別の人口中央値", df.group_by(by = "year").agg( pl.col("pop").quantile(quantile = 0.5) ).head(1) )
display("年度別の人口第3四分位数", df.group_by(by = "year").agg( pl.col("pop").quantile(quantile = 0.75) ).head(1) )
display("年度別の人口最大値", df.group_by(by = "year").agg( pl.col("pop").max() ).head(1) )
display("年度別の人口の和", df.group_by(by = "year").agg( pl.col("pop").sum() ).head(1) )
display("年度別の人口の分散", df.group_by(by = "year").agg( pl.col("pop").var() ).head(1) )
#display("年度別の人口の不偏標準偏差", df.group_by(by = "year").agg( pl.col("pop").sem() ).head(1) )
#display("年度別の人口の基本統計量", df.group_by(by = "year").agg( pl.col("pop").describe() ).head(1) )
display("年度別の人口の最初の要素", df.group_by(by = "year").agg( pl.col("pop").first() ).head(1) )
display("年度別の人口の最後の要素", df.group_by(by = "year").agg( pl.col("pop").last() ).head(1) )
#display("年度別の人口のn番目の要素", df.group_by(by = "year").agg( pl.col("pop").nth() ).head(1) )
8.1.3 集約関数
8.1.3.1 他のライブラリの関数
numpyとの連携が良くわからなかったので省略
8.1.3.2 カスタムのユーザー関数
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
def my_mean(values):
n = len(values)
sum = 0
for value in values:
sum += value
return sum / n
display("カスタムのユーザー関数", df.groupby("year")["lifeExp"].agg(my_mean) )
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
def my_mean(values):
n = len(values)
sum = 0
for value in values:
sum += value
return sum / n
display("カスタムのユーザー関数", df.group_by("year").agg( pl.col("lifeExp").map_elements(my_mean)).sort("year") )
8.1.4 複数の関数を同時に計算する
import pandas as pd
df = pd.read_csv("../data/gapminder.tsv", sep = "\t")
gdf = df\
.groupby("year")\
.agg({
"lifeExp": "mean",
"pop": "median",
"gdpPercap": "median"
})
display("年度別に、余命のデータ数と、人口の平均値とGDPの中央値を計算する", gdf)
import polars as pl
df = pl.read_csv("../data/gapminder.tsv", separator = "\t")
gdf = df\
.group_by("year")\
.agg([pl.col("lifeExp").count().alias("mean"),
pl.col("pop").mean().alias("mean"),
pl.col("gdpPercap").std().alias("median")])
display("年度別に、余命の平均値と、人口の平均値とGDPの中央値を計算する", gdf)
8.1.5 .agg/aggregateでdictを使う
8.1.5.1 DataFrameに対するdictの指定
省略
8.2 変換(transform)
8.2.1 zスコアの例
polarsにはtransformが無いので省略
8.2.2 欠損値の例
この句はpandasで書いている
8.3 フィルタリング
import pandas as pd
import seaborn as sns
tips = pd.DataFrame( sns.load_dataset("tips") )
print("元データの要素数", tips.shape)
display("size列の集計", tips["size"].value_counts())
tips_filtered = tips.groupby(by = "size").filter(lambda x: x["size"].count() >= 30)
display("要素数が30個以上のデータを抽出した", tips_filtered)
print("要素数", tips_filtered.shape)
import polars as pl
import seaborn as sns
tips = pl.DataFrame( sns.load_dataset("tips") )
print("元データの要素数", tips.shape)
display("size列の集計", tips["size"].value_counts())
tips_filtered = tips.group_by(by = "size").agg( pl.col("size").count().alias("counts") ).filter( pl.col("counts") >= 30 )
display("要素数が30個以上のデータを抽出した", tips_filtered)
print("要素数", tips_filtered.shape)
おわりに
3月の記事と比較すると、私のPython力(ちから)が向上しているのを感じます。
継続は力なりですね。
Discussion