Pandas & NumPy Academy · Pelajaran

Tetingkap Mengembang

Kira statistik terkumpul yang merangkumi semua baris dari awal hingga setiap titik menggunakan expanding().sum().

Pelajaran 2 daripada 413 langkah

Tetingkap Mengembang ialah pelajaran Pandas & NumPy Academy percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Pandas & NumPy Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Pandas & NumPy Academy merangkumi sejumlah 4 pelajaran.

Apakah Tetingkap Expanding?

Tetingkap expanding merangkumi semua baris dari permulaan Series sehingga baris semasa — tetingkap ini berkembang dengan setiap baris baharu dan bukannya kekal tetap. Pada baris 0, tetingkap mengandungi satu nilai sahaja; pada baris 5, ia mengandungi enam nilai; dan pada baris 100, ia mengandungi 101 nilai. Tetingkap expanding digunakan untuk mengira statistik terkumpul yang mewakili jumlah berjalan, purata berjalan atau nilai maksimum berjalan dari permulaan set data hingga titik masa semasa.

import pandas as pd
import numpy as np

sales = pd.Series(
    [100, 150, 120, 200, 180, 160, 220, 190],
    index=pd.date_range('2024-01-01', periods=8)
)

# Expanding mean — grows with each row
df = pd.DataFrame({'sales': sales})
df['cumulative_mean'] = df['sales'].expanding().mean()
print(df)

Kaedah expanding()

Series.expanding(min_periods=1) mengembalikan objek Expanding. Parameter min_periods (lalai 1) menetapkan bilangan pemerhatian minimum yang diperlukan untuk hasil bukan-NaN pertama. Tidak seperti rolling(n), tetingkap dalam expanding() tidak tetap — ia sentiasa bermula dari permulaan. Rantaikan sebarang pengagregatan: .sum(), .mean(), .std(), .min(), .max().

import pandas as pd
import numpy as np

np.random.seed(42)
monthly_revenue = pd.Series(
    np.random.randint(500, 1500, 12),
    index=pd.date_range('2024-01', periods=12, freq='ME'),
    name='revenue'
)

df = pd.DataFrame({'revenue': monthly_revenue})
df['cumsum'] = df['revenue'].expanding().sum()
df['cummean'] = df['revenue'].expanding().mean()
df['cummax'] = df['revenue'].expanding().max()
df['cummin'] = df['revenue'].expanding().min()
print(df)

cumsum, cumprod, cummax, cummin Pandas

Untuk statistik terkumpul yang paling biasa, Pandas menyediakan kaedah terus pada Series dan DataFrame tanpa memerlukan expanding(): cumsum(), cumprod(), cummax() dan cummin(). Ini ialah pelaksanaan yang dioptimumkan dan sedikit lebih pantas berbanding padanan expanding(). Gunakan pintasan ini untuk metrik perniagaan biasa seperti hasil tahun hingga kini (cumsum) atau harga maksimum sepanjang masa (cummax).

import pandas as pd
import numpy as np

prices = pd.Series(
    [100, 95, 110, 105, 120, 115, 130, 125],
    index=pd.date_range('2024-01-01', periods=8)
)

df = pd.DataFrame({'price': prices})
df['cummax'] = df['price'].cummax()    # all-time high
df['cummin'] = df['price'].cummin()    # all-time low
df['cumsum'] = df['price'].cumsum()    # cumulative total
df['cumprod'] = (1 + df['price'].pct_change()).cumprod()  # growth index
print(df.round(3))

Pengiraan Tahun hingga Kini dengan Expanding

Penggunaan klasik tetingkap expanding ialah hasil tahun hingga kini (YTD). Bagi setiap hari, anda mahu jumlah semua hasil dari 1 Januari tahun semasa hingga hari tersebut. Ini hanyalah cumsum() yang digunakan dalam setiap kumpulan tahun. Laksanakannya dengan groupby(year).cumsum() — cumsum akan dimulakan semula pada permulaan setiap tahun kalendar sambil mengumpul nilai sepanjang tahun.

import pandas as pd
import numpy as np

np.random.seed(0)
dates = pd.date_range('2023-01-01', '2024-06-30', freq='ME')
daily = pd.DataFrame({
    'date': dates,
    'revenue': np.random.randint(100, 500, len(dates))
})

# Year-to-date cumulative revenue
daily['year'] = daily['date'].dt.year
daily['ytd_revenue'] = daily.groupby('year')['revenue'].cumsum()
daily = daily.drop(columns='year')
print(daily.tail(10).to_string(index=False))

Sisihan Piawai Tetingkap Expanding

expanding().std() mengira sisihan piawai berjalan menggunakan semua data dari permulaan hingga baris semasa. Ini berguna untuk memantau sama ada kebolehubahan sesuatu metrik meningkat atau menurun dari semasa ke semasa — contohnya, menjejaki sama ada jualan harian sesuatu produk menjadi lebih atau kurang boleh dijangka apabila perniagaan semakin matang. Tidak seperti std rolling (yang hanya mencerminkan kebolehubahan terkini), std expanding menangkap keseluruhan serakan sejarah.

import pandas as pd
import numpy as np

np.random.seed(42)
sales = pd.Series(
    np.concatenate([
        np.random.normal(100, 5, 30),   # stable period
        np.random.normal(100, 25, 30)   # volatile period
    ]),
    index=pd.date_range('2024-01-01', periods=60)
)

df = pd.DataFrame({'sales': sales})
df['expanding_std'] = df['sales'].expanding().std()
df['rolling_30d_std'] = df['sales'].rolling(30).std()
print(df.tail(10).round(2))

Membandingkan Rolling dengan Expanding

Perbezaan utama: tetingkap rolling mencerminkan prestasi terkini (n hari terakhir) dan tidak dipengaruhi oleh data yang sudah lama, manakala tetingkap expanding merangkumi keseluruhan sejarah dan oleh itu bergerak perlahan ke arah nilai yang stabil. Gunakan rolling apabila anda mengambil berat tentang trend terkini (purata bergerak 7 hari lebih responsif terhadap perubahan terkini berbanding purata 90 hari). Gunakan expanding apabila anda mahukan statistik sepanjang masa atau metrik YTD yang tidak boleh melupakan data terdahulu.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(10)
data = pd.Series(
    np.random.randn(60).cumsum() + 50,
    index=pd.date_range('2024-01-01', periods=60)
)

df = pd.DataFrame({'value': data})
df['rolling_10'] = data.rolling(10).mean()
df['expanding'] = data.expanding().mean()

df.plot(figsize=(12, 5), title='Rolling 10-day Mean vs. Expanding Mean')
plt.ylabel('Value')
plt.show()

Apply Expanding untuk Statistik Terkumpul Tersuai

expanding().apply(func) menggunakan fungsi tersuai pada semua data dari permulaan hingga baris semasa, sama seperti rolling().apply(). Ini membolehkan pengiraan statistik terkumpul yang tidak tersedia sebagai fungsi terbina dalam — contohnya, pekali variasi terkumpul (std/mean), median berjalan atau nisbah Sharpe terkumpul. Fungsi tersebut menerima tatasusunan NumPy yang mengandungi semua nilai yang telah dilihat setakat ini dan mesti mengembalikan satu nilai skalar.

import pandas as pd
import numpy as np

np.random.seed(0)
returns = pd.Series(
    np.random.normal(0.001, 0.02, 60),
    index=pd.date_range('2024-01-01', periods=60)
)

# Cumulative Sharpe ratio (mean/std of returns)
def sharpe(arr):
    if len(arr) < 2:
        return float('nan')
    return arr.mean() / arr.std() * (252 ** 0.5)  # annualised

df = pd.DataFrame({'returns': returns})
df['cum_sharpe'] = df['returns'].expanding().apply(sharpe, raw=True)
print(df.tail(8).round(4))

Tetingkap Expanding dengan Pengendalian NaN

Tetingkap expanding mengabaikan nilai NaN secara lalai — NaN di tengah-tengah Series diabaikan apabila jumlah atau min terkumpul dikira. Anda boleh menyemak perkara ini dengan skipna=True (lalai dalam kebanyakan pengagregatan Pandas). Apabila anda mempunyai siri masa dengan nilai yang benar-benar hilang (contohnya, tiada dagangan pada hujung minggu), statistik expanding akan dikira hanya daripada nilai bukan-NaN yang telah dilihat setakat ini, dan ini biasanya tingkah laku yang diingini.

import pandas as pd
import numpy as np

data = pd.Series([10, np.nan, 20, 30, np.nan, 40, 50])

# cumsum skips NaN by default
df = pd.DataFrame({'value': data})
df['cumsum'] = df['value'].cumsum()      # NaN propagates in cumsum!
df['expanding_sum'] = df['value'].expanding().sum()  # NaN skipped

print(df)
print('\nNote: cumsum propagates NaN; expanding().sum() skips it.')

Tetingkap Expanding untuk Penanda Aras Berjalan

Tetingkap expanding sangat sesuai untuk mengira penanda aras berjalan: nilai maksimum sepanjang masa, suku tahun terbaik yang pernah dicapai atau kadar ralat terendah sejak pelancaran. KPI ini memerlukan semua nilai sejarah untuk diingati — tetingkap rolling akan melupakan rekod lama. Menggunakan cummax() atau cummin() mengembalikan pencapaian terbaik (atau terburuk) yang berjalan pada setiap titik, sekali gus memudahkan penjejakan masa rekod baharu dicapai.

import pandas as pd
import numpy as np

np.random.seed(5)
sales = pd.Series(
    np.random.randint(100, 300, 20),
    index=pd.date_range('2024-01-01', periods=20),
    name='daily_sales'
)

df = pd.DataFrame({'sales': sales})
df['all_time_max'] = df['sales'].cummax()
df['new_record'] = df['sales'] == df['all_time_max']

print('Days where a new sales record was set:')
print(df[df['new_record']].drop(columns='new_record'))

Contoh Praktikal: Pulangan Terkumpul

Dalam kewangan, pulangan terkumpul menunjukkan jumlah pertumbuhan pelaburan dari tarikh mula hingga setiap tarikh berikutnya. Bermula dengan pulangan peratusan harian, hasil darab terkumpul (1 + daily_return) memberikan faktor pertumbuhan keseluruhan. Hasil darab expanding lebih sesuai berbanding hasil darab rolling di sini — anda mahu menjejaki jumlah pertumbuhan sejak permulaan, bukan hanya sepanjang n hari terakhir.

import pandas as pd
import numpy as np

np.random.seed(7)
start_price = 100
daily_returns = pd.Series(
    np.random.normal(0.0005, 0.015, 252),
    index=pd.date_range('2024-01-01', periods=252)
)

# Cumulative return = product of (1 + r_i)
cum_returns = (1 + daily_returns).cumprod()
portfolio_value = start_price * cum_returns

print(f'Start value: ${start_price:.2f}')
print(f'End value:   ${portfolio_value.iloc[-1]:.2f}')
print(f'Total return: {(portfolio_value.iloc[-1]/start_price - 1)*100:.1f}%')

Bila Perlu Menggunakan Expanding, Rolling atau cumsum

Panduan untuk memilih pendekatan yang tepat:

  • Gunakan cumsum() / cummax() / cummin() untuk pengagregatan terkumpul yang mudah — ini ialah pilihan paling pantas.
  • Gunakan expanding().mean() / std() apabila anda memerlukan purata berjalan atau varians terkumpul.
  • Gunakan expanding().apply(custom_func) untuk statistik sepanjang masa yang kompleks dan tidak tersedia sebagai fungsi terbina dalam.
  • Gunakan rolling(n) dan bukannya expanding apabila hanya sejarah terkini patut mempengaruhi nilai semasa.

Semakan Pantas

Uji pemahaman anda tentang tetingkap expanding daripada pelajaran ini.

Ulang Kaji Pelajaran

Dalam pelajaran ini, anda telah mempelajari bahawa expanding() mengira statistik terkumpul menggunakan tetingkap yang berkembang dari permulaan Series, cumsum/cummax/cummin ialah pintasan yang dioptimumkan untuk operasi terkumpul biasa, dan tetingkap expanding sesuai untuk rekod sepanjang masa, metrik YTD serta pulangan pelaburan terkumpul. Seterusnya, kita akan meneroka purata bergerak berwajaran eksponen (EWMA) — yang memberikan lebih berat kepada pemerhatian terkini.

Percuma untuk bermula

Pelajari Python dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
30
Pelajaran
120

Soalan Lazim

Adakah pelajaran “Tetingkap Mengembang” percuma?

Ya — teks penuh “Tetingkap Mengembang” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Pandas & NumPy Academy, tingkat taraf kepada CoddyKit PRO. Kursus Pandas & NumPy Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Tetingkap Mengembang”?

Kira statistik terkumpul yang merangkumi semua baris dari awal hingga setiap titik menggunakan expanding().sum(). Anda berlatih Pandas & NumPy Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Pandas & NumPy Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Pandas & NumPy Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.

Berapa lamakah pelajaran “Tetingkap Mengembang” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Pandas & NumPy Academy ini?

Ya. Setiap pelajaran Pandas & NumPy Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Tetingkap Bergerak
  2. Tetingkap Mengembang
  3. Purata Bergerak Berpemberat Eksponen
  4. Kedudukan dan Persentil dalam Kumpulan
← Kembali ke Pandas & NumPy Academy