σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft Academyロードマップ
Ctrl K
AO
+1.2k 人の学習者
ログイン参加する ↗
ロードマップ
AO
+1.2k 人の学習者
ログイン
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Python ロードマップ›モジュール 2 · 市場データのためのNumPyとpandas›トピック 2.6·~45 分初級

pandasのDataFrame

ロードマップ上の位置モジュール 2/11 · トピック 6/20
2.6 pandasのDataFrame
—ラボスコア— / 100合計XP—連続日数—

ラベル付きの列でできた表

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.25
import 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']
新しい表を返し、呼び出し側の表を書き換えないDataFrame を受け取る関数は、それを読み取り専用として扱い、新しい DataFrame を返すべきです。新しい表を返す 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点
エクスプローラー · lab-39-1
▾ lab-39-1
…
bash · ブラウザ内
learner@quantcraft:~/lab-39-1$
Pythonは未読み込みPythonLn 1, Col 1Spaces: 4UTF-8

このトピックをリセットしますか?

lab-39-1 の内容はすべてスターターファイルに戻り、ターミナルも消去されます。現在の解答は失われ、元に戻せません。

リセットされるもの
  • main.py → スターターコード
  • ターミナル履歴とテスト出力
  • 未提出の変更
保持されるもの
  • ラボの最高スコア
  • XPと連続日数
  • 講義の進捗とメモ

コードを実行するにはログインしてください。

レクチャーはすべて無料で読めます。コードの実行、テスト、ラボの提出にはアカウントの作成かログインが必要です。

  • ブラウザ内IDEとbashターミナル。インストール不要
  • 即時採点、XP、ロードマップでの現在地
アカウントを作成ログイン
または
GitHubで続ける