تحلیل سری‌های زمانی با Pandas در پایتون: راهنمای عملی

تحلیل سری‌های زمانی با Pandas 3.0 را از صفر یاد بگیرید. آموزش DatetimeIndex، Resampling، Rolling Window، Shifting و تغییرات پنداز ۳.۰ با مثال‌های عملی و کد آماده اجرا.

مقدمه: چرا تحلیل سری‌های زمانی مهم است؟

سری‌های زمانی (Time Series) واقعاً همه‌جا هستند. قیمت سهام، ارزهای دیجیتال، داده‌های آب‌وهوایی، ترافیک وب‌سایت، فروش ماهانه و حتی ضربان قلب — هر داده‌ای که در طول زمان ثبت شده باشد، عملاً یک سری زمانی محسوب می‌شه. تحلیل این داده‌ها بهتون امکان می‌ده روندها رو شناسایی کنید، الگوهای فصلی رو کشف کنید و حتی آینده رو پیش‌بینی کنید.

Pandas از همون اول برای کار با داده‌های مالی و سری‌های زمانی طراحی شد. صادقانه بگم، هنوز هم قدرتمندترین ابزار پایتون برای دست‌کاری داده‌های زمانیه.

با انتشار پنداز ۳.۰ در ژانویه ۲۰۲۶، تغییرات مهمی در نحوه کار با تاریخ و زمان اعمال شده که درک‌شون برای هر توسعه‌دهنده‌ای ضروریه. در این راهنما همه چیز رو از صفر تا پیشرفته پوشش می‌دیم: از ساخت ایندکس‌های زمانی و تبدیل تاریخ، تا Resampling، Rolling Window، Shifting و تغییرات جدید پنداز ۳.۰. همه مثال‌ها عملی هستن و می‌تونید مستقیماً توی پروژه‌هاتون استفاده‌شون کنید.

پیش‌نیازها و نصب

برای دنبال کردن این آموزش، به پایتون ۳.۱۰ یا بالاتر و پنداز ۳.۰ نیاز دارید. NumPy و Matplotlib رو هم نصب کنید:

pip install pandas>=3.0 numpy matplotlib

بررسی نسخه نصب‌شده:

import pandas as pd
print(pd.__version__)  # 3.0.1 or higher

ساختارهای پایه سری زمانی در Pandas

Timestamp: واحد پایه زمان

کلاس pd.Timestamp معادل یک لحظه خاص در زمانه — مثل یک سلول تاریخ در اکسل، ولی خیلی قدرتمندتر. بذارید با یه مثال ساده شروع کنیم:

import pandas as pd

# ساخت Timestamp
ts = pd.Timestamp("2026-03-12 14:30:00")
print(ts)             # 2026-03-12 14:30:00
print(ts.year)        # 2026
print(ts.month)       # 3
print(ts.day_name())  # Thursday
print(ts.quarter)     # 1

# تبدیل تاریخ شمسی به میلادی و ساخت Timestamp
# (نیاز به کتابخانه jdatetime یا تبدیل دستی)
ts_persian = pd.Timestamp("2026-03-21")  # ۱ فروردین ۱۴۰۵
print(ts_persian.day_name())  # Saturday

DatetimeIndex: ایندکس زمانی

DatetimeIndex مجموعه‌ای مرتب از Timestamp‌هاست که به عنوان ایندکس یک Series یا DataFrame استفاده می‌شه. این ساختار، کلید اصلی تحلیل سری‌های زمانی در Pandas محسوب می‌شه و تقریباً همه عملیات‌های زمانی از اینجا شروع می‌شن:

import pandas as pd
import numpy as np

# ساخت DatetimeIndex با date_range
dates = pd.date_range(start="2026-01-01", periods=12, freq="MS")
# MS = Month Start (اول هر ماه)

print(dates)
# DatetimeIndex(['2026-01-01', '2026-02-01', ..., '2026-12-01'],
#               dtype='datetime64[us]', freq='MS')

# ساخت Series با ایندکس زمانی
sales = pd.Series(
    np.random.randint(100, 500, size=12),
    index=dates,
    name="monthly_sales"
)
print(sales)

فرکانس‌های رایج در date_range

این جدول مهم‌ترین فرکانس‌هایی که توی pd.date_range() استفاده می‌شن رو نشون می‌ده (پیشنهاد می‌کنم یه جایی ذخیره‌ش کنید چون خیلی بهش نیاز پیدا می‌کنید):

  • D — روزانه (تقویمی)
  • B — روز کاری (بدون شنبه و یکشنبه)
  • W — هفتگی
  • MS — اول هر ماه
  • ME — آخر هر ماه
  • QS — اول هر فصل
  • YS — اول هر سال
  • h — ساعتی
  • min — دقیقه‌ای
  • s — ثانیه‌ای
# ساخت بازه‌های زمانی مختلف
hourly = pd.date_range("2026-03-12", periods=24, freq="h")
quarterly = pd.date_range("2026-01-01", periods=4, freq="QS")
business_days = pd.date_range("2026-03-01", "2026-03-31", freq="B")

print(f"Business days in March 2026: {len(business_days)}")

تبدیل داده‌ها به فرمت زمانی با to_datetime()

خب، بریم سراغ یکی از مهم‌ترین بخش‌ها. توی دنیای واقعی، داده‌های تاریخ معمولاً به صورت رشته‌ای (string) از فایل CSV یا دیتابیس خونده می‌شن. تابع pd.to_datetime() این رشته‌ها رو به فرمت datetime64 تبدیل می‌کنه:

import pandas as pd

# خواندن داده نمونه
df = pd.DataFrame({
    "date": ["2026-01-15", "2026-02-20", "2026-03-10", "2026-04-05"],
    "revenue": [15000, 22000, 18500, 25000],
    "orders": [120, 180, 150, 200]
})

# تبدیل ستون date به datetime
df["date"] = pd.to_datetime(df["date"])
print(df.dtypes)
# date       datetime64[us]   ← در پنداز ۳.۰ دقت پیش‌فرض میکروثانیه است
# revenue             int64
# orders              int64

# تنظیم به عنوان ایندکس
df = df.set_index("date")
print(df)

کار با فرمت‌های مختلف تاریخ

تابع to_datetime() می‌تونه فرمت‌های مختلف رو خودکار شناسایی کنه، ولی یه نکته مهم: برای عملکرد بهتر، فرمت رو صراحتاً مشخص کنید. تجربه نشون داده وقتی حجم داده‌ها بالا می‌ره، مشخص کردن فرمت سرعت تبدیل رو تا ۱۰ برابر افزایش می‌ده:

# فرمت‌های مختلف تاریخ
dates_mixed = pd.Series([
    "15/01/2026",    # روز/ماه/سال
    "20-Feb-2026",   # انگلیسی
    "2026.03.10",    # نقطه‌ای
])

# تبدیل با فرمت مشخص
result1 = pd.to_datetime("15/01/2026", format="%d/%m/%Y")
result2 = pd.to_datetime("20-Feb-2026", format="%d-%b-%Y")

print(result1)  # 2026-01-15 00:00:00
print(result2)  # 2026-02-20 00:00:00

# مدیریت خطا در تبدیل
messy_dates = pd.Series(["2026-01-01", "invalid", "2026-03-01"])
clean_dates = pd.to_datetime(messy_dates, errors="coerce")
print(clean_dates)
# 0   2026-01-01
# 1          NaT    ← Not a Time (مقدار نامعتبر)
# 2   2026-03-01

نکته‌ای که خیلی‌ها ازش غافلن: پارامتر errors="coerce" مقادیر نامعتبر رو به جای ارور دادن، به NaT تبدیل می‌کنه. توی پروژه‌های واقعی که داده‌ها همیشه تمیز نیستن، این خیلی به کار میاد.

ایندکس‌گذاری و فیلتر زمانی

یکی از قابلیت‌هایی که واقعاً Pandas رو از بقیه ابزارها متمایز می‌کنه، امکان فیلتر کردن داده‌ها بر اساس بازه‌های زمانی فقط با استفاده از رشته‌هاست. اولین بار که این قابلیت رو دیدم، جداً شگفت‌زده شدم:

import pandas as pd
import numpy as np

# ساخت داده نمونه: فروش روزانه یک سال
dates = pd.date_range("2025-01-01", "2025-12-31", freq="D")
daily_sales = pd.Series(
    np.random.normal(1000, 200, len(dates)),
    index=dates,
    name="sales"
)

# فیلتر بر اساس سال
march_data = daily_sales["2025-03"]
print(f"March entries: {len(march_data)}")  # 31

# فیلتر بر اساس بازه
q1_data = daily_sales["2025-01":"2025-03"]
print(f"Q1 entries: {len(q1_data)}")  # 90

# فیلتر یک روز خاص
single_day = daily_sales["2025-06-15"]
print(f"Sales on June 15: {single_day:.0f}")

# فیلتر با between_time (برای داده‌های ساعتی)
hourly = pd.Series(
    np.random.randn(24*7),
    index=pd.date_range("2026-03-01", periods=24*7, freq="h")
)
# فقط ساعات کاری (۹ صبح تا ۵ عصر)
work_hours = hourly.between_time("09:00", "17:00")
print(f"Work hour entries: {len(work_hours)}")

استخراج اجزای تاریخ با dt accessor

وقتی یک ستون از نوع datetime دارید، با .dt می‌تونید به اجزای مختلفش دسترسی داشته باشید. این accessor خیلی کاربردیه و تقریباً توی هر پروژه تحلیل زمانی ازش استفاده می‌کنم:

import pandas as pd
import numpy as np

df = pd.DataFrame({
    "timestamp": pd.date_range("2026-01-01", periods=100, freq="D"),
    "value": np.random.randn(100)
})

# استخراج اجزای تاریخ
df["year"] = df["timestamp"].dt.year
df["month"] = df["timestamp"].dt.month
df["day_of_week"] = df["timestamp"].dt.day_name()
df["quarter"] = df["timestamp"].dt.quarter
df["is_month_end"] = df["timestamp"].dt.is_month_end

print(df.head(10))

Resampling: تغییر فرکانس سری زمانی

Resampling یکی از مهم‌ترین عملیات‌ها توی تحلیل سری‌های زمانیه و شاید بشه گفت یکی از دلایل اصلی محبوبیت Pandas برای کار با داده‌های زمانی. این عملیات فرکانس داده‌ها رو تغییر می‌ده — مثلاً تبدیل داده‌های روزانه به ماهانه (Downsampling) یا برعکس (Upsampling).

Downsampling: کاهش فرکانس

import pandas as pd
import numpy as np

# داده‌های روزانه فروش
dates = pd.date_range("2025-01-01", "2025-12-31", freq="D")
daily = pd.DataFrame({
    "sales": np.random.normal(5000, 1000, len(dates)),
    "visitors": np.random.randint(200, 800, len(dates))
}, index=dates)

# تبدیل به ماهانه — مجموع فروش و میانگین بازدیدکنندگان
monthly = daily.resample("MS").agg({
    "sales": "sum",
    "visitors": "mean"
})
print(monthly.head())

# تبدیل به هفتگی — با توابع تجمیعی مختلف
weekly = daily.resample("W").agg({
    "sales": ["sum", "mean", "max"],
    "visitors": ["mean", "std"]
})
print(weekly.head())

# تبدیل به فصلی
quarterly = daily["sales"].resample("QS").agg(["sum", "mean", "std"])
print(quarterly)

Upsampling: افزایش فرکانس

حالا فرض کنید داده‌های ماهانه دارید و می‌خواید تخمینی از مقادیر روزانه داشته باشید. اینجاست که Upsampling به کار میاد:

# داده‌های ماهانه
monthly_data = pd.Series(
    [100, 120, 135, 115, 140, 160],
    index=pd.date_range("2026-01-01", periods=6, freq="MS"),
    name="monthly_metric"
)

# Upsampling به روزانه — مقادیر خالی ایجاد می‌شود
daily_upsampled = monthly_data.resample("D").asfreq()
print(daily_upsampled.head(10))
# 2026-01-01    100.0
# 2026-01-02      NaN
# 2026-01-03      NaN
# ...

# پر کردن با روش Forward Fill
daily_ffill = monthly_data.resample("D").ffill()

# پر کردن با درون‌یابی (Interpolation)
daily_interp = monthly_data.resample("D").interpolate(method="linear")

print("Forward Fill:", daily_ffill.head(5).values)
print("Interpolation:", daily_interp.head(5).values)

Rolling Window: پنجره متحرک

خب، رسیدیم به یکی از پرکاربردترین تکنیک‌ها. پنجره متحرک (Rolling Window) بهتون اجازه می‌ده میانگین متحرک، انحراف معیار متحرک و کلی آمار دیگه رو محاسبه کنید. اگه با تحلیل تکنیکال بازارهای مالی آشنا باشید، حتماً با این مفهوم برخورد داشتید.

این ابزار برای هموارسازی نویز و شناسایی روندها واقعاً ضروریه.

میانگین متحرک (Moving Average)

import pandas as pd
import numpy as np

# داده‌های روزانه قیمت
np.random.seed(42)
dates = pd.date_range("2025-01-01", "2025-12-31", freq="D")
price = pd.Series(
    np.cumsum(np.random.randn(len(dates))) + 100,
    index=dates,
    name="price"
)

# میانگین متحرک ۷ روزه
ma_7 = price.rolling(window=7).mean()

# میانگین متحرک ۳۰ روزه
ma_30 = price.rolling(window=30).mean()

# انحراف معیار متحرک (نوسان‌پذیری)
vol_30 = price.rolling(window=30).std()

# ترکیب در یک DataFrame
analysis = pd.DataFrame({
    "price": price,
    "MA_7": ma_7,
    "MA_30": ma_30,
    "Volatility_30": vol_30
})

print(analysis.tail(10))

پنجره متحرک مرکزی

به صورت پیش‌فرض، پنجره متحرک به عقب نگاه می‌کنه. یعنی مقدار هر نقطه بر اساس n نقطه قبلی محاسبه می‌شه. اما با center=True می‌تونید پنجره رو متقارن کنید:

# پنجره مرکزی: ۳ روز قبل + امروز + ۳ روز بعد
centered_ma = price.rolling(window=7, center=True).mean()

# مقایسه
comparison = pd.DataFrame({
    "original": price,
    "trailing_MA7": ma_7,
    "centered_MA7": centered_ma
})
print(comparison.iloc[3:10])

توابع سفارشی در Rolling

یکی از قابلیت‌های جالب Rolling اینه که می‌تونید توابع سفارشی خودتون رو بهش بدید:

# تابع سفارشی: محاسبه دامنه (Range)
def price_range(x):
    return x.max() - x.min()

rolling_range = price.rolling(window=14).apply(price_range)

# تابع سفارشی: درصد روزهای مثبت
def pct_positive(x):
    changes = x.diff()
    return (changes > 0).sum() / len(changes) * 100

rolling_pos_pct = price.rolling(window=30).apply(pct_positive)
print(rolling_pos_pct.tail())

میانگین متحرک نمایی (EWM)

میانگین متحرک نمایی وزن بیشتری به داده‌های اخیر می‌ده و توی تحلیل مالی خیلی محبوبه. اگه بین SMA و EWM مردد هستید، به طور کلی EWM سریع‌تر به تغییرات واکنش نشون می‌ده:

# EWM با span=20 (معادل تقریبی MA-20 ولی واکنش‌پذیرتر)
ewm_20 = price.ewm(span=20).mean()

# EWM با halflife=10 (نیمه‌عمر ۱۰ روز)
ewm_hl10 = price.ewm(halflife=10).mean()

result = pd.DataFrame({
    "price": price,
    "SMA_20": price.rolling(20).mean(),
    "EWM_20": ewm_20
})
print(result.tail())

Shifting: جابه‌جایی داده‌ها در زمان

متد shift() داده‌ها رو به جلو یا عقب در زمان جابه‌جا می‌کنه بدون اینکه ایندکس تغییر کنه. این تکنیک رو خیلی دست‌کم نگیرید — برای محاسبه تغییرات، نرخ رشد و مخصوصاً ایجاد ویژگی‌های تأخیری (lag features) توی مدل‌های یادگیری ماشین فوق‌العاده کاربردیه.

محاسبه تغییرات و نرخ رشد

import pandas as pd
import numpy as np

# داده‌های ماهانه فروش
monthly_sales = pd.Series(
    [450, 520, 480, 610, 570, 680, 720, 650, 710, 800, 850, 920],
    index=pd.date_range("2025-01-01", periods=12, freq="MS"),
    name="sales"
)

# مقدار ماه قبل
previous_month = monthly_sales.shift(1)

# تغییر نسبت به ماه قبل (مطلق)
monthly_change = monthly_sales - monthly_sales.shift(1)

# نرخ رشد ماهانه (درصدی)
monthly_growth = monthly_sales.pct_change() * 100

# تغییر نسبت به سال قبل (YoY) — shift 12 ماه
# yoy_change = monthly_sales.pct_change(periods=12) * 100

result = pd.DataFrame({
    "sales": monthly_sales,
    "prev_month": previous_month,
    "change": monthly_change,
    "growth_pct": monthly_growth.round(1)
})
print(result)

ایجاد Lag Features برای یادگیری ماشین

یکی از کاربردهای خیلی مهم shift() ساخت ویژگی‌های تأخیری برای مدل‌های پیش‌بینیه. من شخصاً توی اکثر پروژه‌های پیش‌بینی سری زمانی از این تکنیک استفاده می‌کنم و نتایج خوبی گرفتم:

import pandas as pd
import numpy as np

# داده‌های روزانه
dates = pd.date_range("2025-01-01", periods=365, freq="D")
df = pd.DataFrame({
    "value": np.cumsum(np.random.randn(365)) + 50
}, index=dates)

# ساخت lag features
for lag in [1, 3, 7, 14, 30]:
    df[f"lag_{lag}"] = df["value"].shift(lag)

# ساخت rolling features
df["rolling_mean_7"] = df["value"].rolling(7).mean()
df["rolling_std_7"] = df["value"].rolling(7).std()

# حذف ردیف‌های NaN
df_clean = df.dropna()
print(df_clean.head())
print(f"Shape: {df_clean.shape}")

Expanding Window: پنجره انباشتی

برخلاف Rolling که اندازه پنجره‌ش ثابته، expanding() از ابتدای سری شروع می‌کنه و با هر نقطه جدید بزرگ‌تر می‌شه. خیلی ساده بخوام بگم: Rolling مثل نگاه کردن از پنجره قطاره (فقط یه بخش محدود رو می‌بینید)، ولی Expanding مثل نگاه کردن به عقب از بالای کوهه (همه چیز از اول تا الان رو می‌بینید).

import pandas as pd
import numpy as np

dates = pd.date_range("2025-01-01", periods=100, freq="D")
values = pd.Series(np.random.normal(100, 15, 100), index=dates)

# میانگین انباشتی (Cumulative Mean)
expanding_mean = values.expanding().mean()

# حداقل و حداکثر تا هر نقطه
expanding_min = values.expanding().min()
expanding_max = values.expanding().max()

result = pd.DataFrame({
    "value": values,
    "cum_mean": expanding_mean.round(2),
    "cum_min": expanding_min,
    "cum_max": expanding_max
})
print(result.tail(10))

تغییرات سری زمانی در پنداز ۳.۰

اگه از پنداز ۲.x به ۳.۰ مهاجرت می‌کنید، این بخش رو حتماً بخونید. تغییرات مهمی اعمال شده که اگه ازشون بی‌خبر باشید، ممکنه کدهاتون رفتار غیرمنتظره‌ای نشون بدن.

تغییر دقت پیش‌فرض از نانوثانیه به میکروثانیه

توی نسخه‌های قبلی، تبدیل رشته‌ها به datetime همیشه با دقت نانوثانیه (datetime64[ns]) انجام می‌شد. در پنداز ۳.۰، دقت پیش‌فرض به میکروثانیه (datetime64[us]) تغییر کرده:

import pandas as pd

# پنداز ۳.۰ — دقت پیش‌فرض میکروثانیه
ts = pd.to_datetime("2026-03-12")
print(ts)       # 2026-03-12 00:00:00
print(ts.unit)  # us (microsecond)

# ساخت DatetimeIndex — دقت میکروثانیه
dti = pd.date_range("2026-01-01", periods=5, freq="D")
print(dti.dtype)  # datetime64[us]

# اگر نیاز به دقت نانوثانیه دارید:
dti_ns = pd.date_range("2026-01-01", periods=5, freq="D").as_unit("ns")
print(dti_ns.dtype)  # datetime64[ns]

این تغییر یه مزیت عملی خیلی خوب داره: بازه زمانی قابل نمایش از حدود ۱۶۷۸ تا ۲۲۶۲ میلادی (با نانوثانیه) به بیش از ۲۹۰,۰۰۰ سال گسترش پیدا کرده. البته اکثر ما با چنین بازه‌هایی کار نمی‌کنیم، ولی خب خوبه بدونید!

تأثیر Copy-on-Write بر عملیات سری زمانی

با فعال‌سازی پیش‌فرض Copy-on-Write در پنداز ۳.۰، رفتار عملیات فیلتر و تغییر داده‌های زمانی تغییر کرده. این یکی از تغییراتیه که اگه بهش توجه نکنید، ممکنه ساعت‌ها وقتتون رو تلف کنه:

import pandas as pd
import numpy as np

dates = pd.date_range("2026-01-01", periods=30, freq="D")
df = pd.DataFrame({
    "value": np.random.randn(30)
}, index=dates)

# ✅ صحیح: استفاده از .loc
df.loc["2026-01-10":"2026-01-15", "value"] = 0

# ❌ غلط: انتساب زنجیره‌ای — در پنداز ۳.۰ کار نمی‌کند
# df["2026-01-10":"2026-01-15"]["value"] = 0  # بدون تأثیر!

پروژه عملی: تحلیل داده‌های فروش

خب، حالا وقتشه همه چیزایی که یاد گرفتیم رو توی یه پروژه واقعی کنار هم بذاریم. این پروژه شامل ساخت داده، Resampling، محاسبه نرخ رشد، Rolling Average و ساخت Feature برای مدل‌های یادگیری ماشینه:

import pandas as pd
import numpy as np

# ——— ۱. ساخت داده نمونه ———
np.random.seed(2026)
dates = pd.date_range("2024-01-01", "2025-12-31", freq="D")
n = len(dates)

# شبیه‌سازی فروش با روند صعودی و فصلی‌بودن
trend = np.linspace(100, 200, n)
seasonal = 30 * np.sin(np.arange(n) * 2 * np.pi / 365)
noise = np.random.normal(0, 15, n)
sales = trend + seasonal + noise

df = pd.DataFrame({"daily_sales": sales}, index=dates)

# ——— ۲. Resampling ماهانه ———
monthly = df.resample("MS").agg(
    total_sales=("daily_sales", "sum"),
    avg_daily=("daily_sales", "mean"),
    max_day=("daily_sales", "max"),
    min_day=("daily_sales", "min")
)
print("=== Monthly Summary ===")
print(monthly.head())

# ——— ۳. محاسبه نرخ رشد ماهانه ———
monthly["growth_pct"] = monthly["total_sales"].pct_change() * 100
print("
=== Monthly Growth ===")
print(monthly[["total_sales", "growth_pct"]].head())

# ——— ۴. Rolling Average ———
df["MA_7"] = df["daily_sales"].rolling(7).mean()
df["MA_30"] = df["daily_sales"].rolling(30).mean()

# ——— ۵. شناسایی روند ———
df["above_trend"] = df["daily_sales"] > df["MA_30"]

# ——— ۶. مقایسه فصلی ———
df["month"] = df.index.month
df["year"] = df.index.year
seasonal_comparison = df.groupby(["year", "month"])["daily_sales"].mean().unstack(0)
print("
=== Seasonal Comparison ===")
print(seasonal_comparison.round(1))

# ——— ۷. ساخت Feature برای مدل ———
features = pd.DataFrame(index=df.index)
features["value"] = df["daily_sales"]
features["lag_1"] = df["daily_sales"].shift(1)
features["lag_7"] = df["daily_sales"].shift(7)
features["rolling_mean_7"] = df["daily_sales"].rolling(7).mean()
features["rolling_std_7"] = df["daily_sales"].rolling(7).std()
features["day_of_week"] = df.index.dayofweek
features["month"] = df.index.month

features_clean = features.dropna()
print(f"
Feature matrix shape: {features_clean.shape}")
print(features_clean.head())

نکات عملکردی و بهترین شیوه‌ها

چند نکته مهم که از تجربه عملی بهشون رسیدم:

  • ایندکس رو مرتب نگه دارید: عملیات resample() و asfreq() نیاز دارن داده‌ها بر اساس زمان مرتب باشن. همیشه اول یه df.sort_index() بزنید تا خیالتون راحت باشه.
  • از DatetimeIndex استفاده کنید: قرار دادن تاریخ به عنوان ایندکس (به جای یک ستون عادی) عملکرد Resampling و فیلتر زمانی رو به طور چشمگیری بهبود می‌ده.
  • فرمت تاریخ رو مشخص کنید: هنگام استفاده از to_datetime()، حتماً پارامتر format رو مشخص کنید. این کار سرعت تبدیل رو تا ۱۰ برابر افزایش می‌ده.
  • حافظه رو مدیریت کنید: برای داده‌های بزرگ، از .as_unit("s") استفاده کنید تا دقت به ثانیه کاهش پیدا کنه و حافظه کمتری مصرف بشه.
  • از min_periods استفاده کنید: توی rolling() با min_periods می‌تونید حداقل تعداد مشاهدات لازم برای محاسبه رو تنظیم کنید. این‌جوری مقادیر NaN کمتری خواهید داشت.

سوالات متداول (FAQ)

تفاوت بین resample و groupby در Pandas چیست؟

resample() مختص داده‌های سری زمانیه و نیاز به DatetimeIndex داره. این متد فرکانس داده‌ها رو تغییر می‌ده (مثلاً روزانه به ماهانه). در مقابل، groupby() عمومی‌تره و می‌تونه بر اساس هر ستونی گروه‌بندی کنه. برای تحلیل زمانی، resample() هم کارآمدتره و هم خواناتر.

چطور مقادیر گمشده (NaN) در سری زمانی رو مدیریت کنم؟

Pandas چند روش داره: ffill() مقدار قبلی رو تکرار می‌کنه، bfill() مقدار بعدی رو استفاده می‌کنه، و interpolate() مقادیر رو بر اساس روش‌های مختلف درون‌یابی می‌کنه. به عنوان یه قاعده کلی، برای داده‌های مالی معمولاً ffill() و برای داده‌های فیزیکی interpolate(method="linear") مناسب‌تره.

آیا Pandas برای داده‌های سری زمانی خیلی بزرگ مناسبه؟

Pandas تا چند ده میلیون ردیف رو به خوبی مدیریت می‌کنه. ولی اگه داده‌هاتون از این بزرگ‌تره، Polars (با پشتیبانی بومی از سری‌های زمانی) یا DuckDB (برای تحلیل‌های SQL-مانند) گزینه‌های بهتری هستن. یه ترفند هم اینه که اول با resample() حجم داده‌ها رو کم کنید و بعد با Pandas تحلیل‌تون رو انجام بدید.

تفاوت rolling و expanding در Pandas چیست؟

rolling() یک پنجره با اندازه ثابت داره که روی داده‌ها حرکت می‌کنه (مثلاً میانگین ۷ روز اخیر). اما expanding() از ابتدای سری شروع می‌کنه و با هر نقطه جدید، پنجره بزرگ‌تر می‌شه. به زبان ساده، expanding() برای محاسبه آمارهای انباشتی مثل میانگین کل تا هر نقطه عالیه.

چطور منطقه زمانی (Timezone) رو در Pandas مدیریت کنم؟

از tz_localize() برای تخصیص منطقه زمانی به داده‌های بدون منطقه و از tz_convert() برای تبدیل بین مناطق زمانی استفاده کنید. مثال: df.index = df.index.tz_localize("Asia/Tehran") منطقه زمانی ایران رو تنظیم می‌کنه.

درباره نویسنده Editorial Team

Our team of expert writers and editors.