ラベル付きの列でできた表
DataFrame は2次元の表で、行ラベルのインデックスを共有する列(それぞれ Series)の集まりです。市場データ分析の主役で、シンボルや日付ごとに1行、価格・出来高・リターンなどの項目ごとに1列を持ちます。列の辞書 pd.DataFrame({"price": [...], "volume": [...]}, index=symbols) や、行の辞書のリストから作れます。全体で1つの dtype を持つ NumPy 配列と違い、列ごとに dtype があります(価格は float64、出来高は int64)。
import pandas as pd
df = pd.DataFrame(
{"price": [184.25, 410.2, 171.0], "volume": [200, 50, 300]},
index=["AAPL", "MSFT", "GOOG"],
)
print(df)
# price volume
# AAPL 184.25 200
# MSFT 410.20 50
# GOOG 171.00 300
print(df.shape, df.columns.tolist()) # (3, 2) ['price', 'volume']
print(df.dtypes.astype(str).to_dict()) # {'price': 'float64', 'volume': 'int64'}
rows = [{"symbol": "AAPL", "price": 184.25}, {"symbol": "MSFT", "price": 410.2}]
print(pd.DataFrame(rows)) # from a list of row dictionaries
# symbol price
# 0 AAPL 184.25
# 1 MSFT 410.20列・新しい列・絞り込んだ行
df["price"] は1つの列で Series です。リストを使った df[["price"]] は1列の DataFrame です。新しい列は列同士の演算から作ります。df.assign(notional=df["price"] * df["volume"]) は列を追加した新しい表を返し、df はそのままです(df["notional"] = ... は df 自体を変更します)。列に対するブール条件で行を絞り込み(df[df["volume"] >= 100])、df.sort_values("volume", ascending=False) で並べ替え、.head(n) で先頭 n 行を残します。これらはすべて列全体に一度に働くので、列の操作があるのに iterrows() で行をループしてはいけません。
import pandas as pd
df = pd.DataFrame(
{"price": [184.25, 410.2, 171.0], "volume": [200, 50, 300]},
index=["AAPL", "MSFT", "GOOG"],
)
bigger = df.assign(notional=df["price"] * df["volume"]) # a new frame
print(bigger)
# price volume notional
# AAPL 184.25 200 36850.0
# MSFT 410.20 50 20510.0
# GOOG 171.00 300 51300.0
print(df.columns.tolist()) # ['price', 'volume'] df is unchanged
print(df[df["volume"] >= 100]) # rows that pass the test
# price volume
# AAPL 184.25 200
# GOOG 171.00 300
print(df.sort_values("volume", ascending=False).head(2)) # the two biggest volumes
# price volume
# GOOG 171.00 300
# AAPL 184.25 200要約とデータの確認
表は信頼する前に必ず眺めましょう。df.head() は先頭の行、df.shape は (行数, 列数)、df.dtypes は各列の型、df.isna().sum() は列ごとの欠損数、df.describe() は数値列の要約(件数・平均・標準偏差・最小・四分位・最大)を示します。df.mean() のような列のメソッドは列ごとに1つの値を、df.sum(axis=1) は行ごとに1つの値を返します。数値のはずの列の dtype が object や str なら、たいてい文字列が紛れ込んでいます。
import pandas as pd
df = pd.DataFrame(
{"price": [184.25, 410.2, 171.0], "volume": [200, 50, 300]},
index=["AAPL", "MSFT", "GOOG"],
)
print(df.describe().loc[["count", "mean", "max"]])
# price volume
# count 3.00 3.000000
# mean 255.15 183.333333
# max 410.20 300.000000
print(df.mean().to_dict()) # {'price': 255.15, 'volume': 183.33333333333334}
print(df.sum(axis=1).tolist()) # [384.25, 460.2, 471.0] one value per row
print(df.isna().sum().to_dict()) # {'price': 0, 'volume': 0}
# Changing a copy never changes the original (pandas 3 copies on write)
cheap = df[df["price"] < 200].copy()
cheap.loc["AAPL", "price"] = 0.0
print(df.loc["AAPL", "price"]) # 184.25import pandas as pd
rows = [
{"symbol": "AAPL", "price": 184.25, "volume": 200},
{"symbol": "MSFT", "price": 410.2, "volume": 50},
]
df = pd.DataFrame(rows).set_index("symbol") # make a column the row labels
print(df)
# price volume
# symbol
# AAPL 184.25 200
# MSFT 410.20 50
print(df.rename(columns={"price": "px"}).columns.tolist()) # ['px', 'volume']
print(df.drop(columns="volume").columns.tolist()) # ['price']
print(df.reset_index().columns.tolist()) # ['symbol', 'price', 'volume']assign、ブール条件による絞り込み、sort_values を使いましょう。典型的なバグは引数に新しい列を書き込むことで、呼び出し側の表にも黙って列が増えます。ラボのテストが引数の前後を比べるのはそのためです。pd.DataFrame({列: 値}, index=labels)。df["c"]は Series、df[["c"]]は DataFrame。列ごとに dtype があるassignは新しい表に列を追加。df[mask]は行を絞り込み、sort_values(...).head(n)は上位n件を取る- まず確認:
shape・dtypes・head()・describe()・isna().sum()。呼び出し側の表は書き換えない
次は loc と iloc によるデータ選択です。ラベルまたは位置で行と列を正確に選ぶ2つの方法です。
ラボ:採点される内容
make_frameで価格と出来高の表を作る25点add_notionalで約定金額の列を追加する25点filter_liquidで流動性のある行だけを残す25点top_byで任意の列で行をランキングする25点