學習資料科學:yfinance 金融數據擷取與 Pandas 分析實戰
yfinance 專案介紹與實作範例
本篇文章將根據 yfinance GitHub 連結介紹此專案,並示範如何使用它來擷取股票與期貨資料,並運用 Pandas 進行資料分析。
專案簡介
yfinance 是一個 Python 開源函式庫,其主要功能是從 Yahoo Finance! 網站上抓取金融市場數據。透過 yfinance,使用者可以輕鬆地取得股票、指數、貨幣、加密貨幣、ETF、基金以及期貨等金融商品的:
- 歷史價格
- 基本面資料
- 公司資訊
- …等金融數據
重要聲明: yfinance 專案並非由 Yahoo! 公司官方維護或贊助。它是由社群開發者維護,並基於 Yahoo Finance! 提供的公開 API 介面進行開發。因此,使用 yfinance 需注意以下幾點:
- 非官方: yfinance 與 Yahoo! 公司沒有官方關聯。
- 社群維護: 專案的維護與更新仰賴社群貢獻。
- 服務條款: 使用 Yahoo Finance! 數據時,仍需遵守 Yahoo! 服務條款。
專案特色
yfinance 函式庫具有以下特色:
- Pythonic 介面: 提供簡潔易用的 Python 介面,方便使用者快速上手。
- 多元資料: 支援多種金融市場數據,包含歷史價格、股息、股票分割、財報、公司資訊等。
- 靈活應用: 可應用於量化交易、投資分析、數據視覺化等領域。
GitHub 專案結構 (main branch)
雖然我無法直接瀏覽 GitHub 頁面,但根據一般 GitHub 專案的結構, main
分支通常包含以下內容:
yfinance
函式庫程式碼:- 核心程式碼,包含各種模組和函數,用於資料抓取、處理和分析。
- 範例程式碼 (
examples
或notebooks
資料夾):- 示範如何使用 yfinance 進行資料擷取的範例程式。
- 文件 (
README.md
,doc
資料夾):- 專案說明文件、安裝指南、API 文件等,幫助使用者了解和使用 yfinance。
- 授權檔案 (
LICENSE.txt
):- 說明專案的授權條款, yfinance 通常使用 Apache Software License。
- 其他設定檔:
- 例如
.gitignore
(排除不需納入版本控制的檔案)、setup.py
(專案安裝設定檔) 等。
- 例如
實作範例:擷取 Nvidia 股票與黃金期貨資料
以下將示範如何使用 yfinance 擷取 Nvidia 股票 (NVDA) 和黃金期貨 (GC=F) 的歷史價格資料。
1. 安裝 yfinance
首先,您需要在 Python 環境中安裝 yfinance 函式庫。您可以使用 pip
指令進行安裝:
pip install yfinance
2. Python 程式碼範例
import yfinance as yf
# 擷取 Nvidia 股票 (NVDA) 歷史資料
nvda = yf.Ticker("NVDA")
nvda_history = nvda.history(period="1mo") # 擷取近一個月的資料
print("Nvidia 股票近一個月歷史資料:")
print(nvda_history)
# 擷取 黃金期貨 (GC=F) 歷史資料
gold = yf.Ticker("GC=F")
gold_history = gold.history(period="1mo") # 擷取近一個月的資料
print("\n黃金期貨近一個月歷史資料:")
print(gold_history)
程式碼說明:
import yfinance as yf
: 導入 yfinance 函式庫,並簡稱為yf
。yf.Ticker("NVDA")
: 建立 Nvidia 股票的Ticker
物件。股票代碼 (Ticker Symbol) 為"NVDA"
。yf.Ticker("GC=F")
: 建立 黃金期貨 的Ticker
物件。黃金期貨在 Yahoo Finance! 的代碼為"GC=F"
。.history(period="1mo")
: 呼叫history()
方法,設定period="1mo"
參數,表示擷取 “近一個月” 的歷史資料。您可以調整period
參數來設定不同的時間範圍 (例如"1d"
,"5d"
,"1wk"
,"1mo"
,"3mo"
,"6mo"
,"1y"
,"2y"
,"5y"
,"10y"
,"ytd"
,"max"
)。print(nvda_history)
和print(gold_history)
: 印出擷取到的歷史資料,資料格式為 Pandas DataFrame。
3. 執行結果
執行上述 Python 程式碼後,您將在終端機看到類似以下的輸出結果 (資料會隨著時間變動):
Nvidia 股票近一個月歷史資料:
Open High Low Close Volume Dividends Stock Splits
Date
2025-02-10 708.529999 727.880005 708.529999 721.280029 43575300 0.0 0.0
2025-02-11 724.440002 736.479980 715.539978 726.659973 45874900 0.0 0.0
...
2025-03-07 868.340027 875.239990 855.140015 875.200012 46497500 0.0 0.0
2025-03-08 880.000000 888.559998 869.500000 875.760010 42888700 0.0 0.0
黃金期貨近一個月歷史資料:
Open High Low Close Volume Dividends Stock Splits
Date
2025-02-10 2024.700073 2035.599976 2014.099976 2024.099976 140.0 0.0 0.0
2025-02-11 2023.900024 2033.599976 2016.500000 2029.400024 148.0 0.0 0.0
...
2025-03-07 2158.000000 2174.500000 2154.199951 2165.299805 155.0 0.0 0.0
2025-03-08 2170.000000 2178.199951 2155.000000 2160.399902 131.0 0.0 0.0
4. 進階應用
除了歷史價格, yfinance 還可以擷取更多資料,例如:
- 股息與股票分割: 使用
.dividends
和.splits
屬性。 - 公司資訊: 使用
.info
屬性,包含公司簡介、產業、員工數等。 - 財報: 使用
.financials
,.balancesheet
,.cashflow
,.earnings
等屬性。 - 即時報價: 使用
.fast_info
屬性 (可能需要搭配其他方法或調整參數)。
假設資料已成功載入 Pandas DataFrame,並說明如何使用 Pandas 進行資料分析處理,包含您提及的資料結合、操作、聚合、遺漏值與異常值處理、時間序列資料處理以及移動平均等方法。
請您先將 CSV 檔案下載至您的環境中,並使用 Pandas 載入資料,即可參考以下說明進行資料分析。
假設情境:
假設您已將 CSV 檔案 SOLB-BR-1d-bad-div-fixed.csv
讀取到 Pandas DataFrame 中,並命名為 df
。
import pandas as pd
# 假設已讀取 CSV 檔案
# df = pd.read_csv('SOLB-BR-1d-bad-div-fixed.csv')
# 為了示範,我們建立一個簡化的 DataFrame
data = {'Date': pd.to_datetime(['2024-01-01', '2024-01-02', '2024-01-03', '2024-01-04', '2024-01-05']),
'Open': [10, 11, 12, 13, 14],
'High': [15, 16, 17, 18, 19],
'Low': [9, 10, 11, 12, 13],
'Close': [12, 13, 14, 15, 16],
'Volume': [100, 150, 200, 250, 300],
'Dividends': [0.1, 0, 0, 0.2, 0],
'Stock Splits': [1, 1, 1, 2, 1]}
df = pd.DataFrame(data)
print(df)
資料分析處理說明 (基於 Pandas DataFrame df
)
1. 資料的結合
情境: 假設您有另一個包含補充資訊的 DataFrame,例如基本面資料或額外的技術指標,您想將其與 df
結合。
方法: Pandas 提供 pd.concat()
和 pd.merge()
函數進行資料結合。
pd.concat()
: 沿著軸線 (行或列) 將 DataFrame 或 Series 物件串聯起來。pd.merge()
: 根據共同欄位 (類似 SQL 的 JOIN 操作) 將 DataFrame 合併。
範例 (假設 df2
是另一個 DataFrame,且有共同的 'Date'
欄位):
# 假設 df2 是另一個 DataFrame
data2 = {'Date': pd.to_datetime(['2024-01-01', '2024-01-02', '2024-01-03', '2024-01-06']),
'Indicator': [20, 21, 22, 23]}
df2 = pd.DataFrame(data2)
# 使用 pd.merge() 根據 'Date' 欄位結合 df 和 df2 (inner join)
df_merged = pd.merge(df, df2, on='Date', how='inner')
print("合併後的 DataFrame (inner join):")
print(df_merged)
# 使用 pd.concat() 沿著列方向堆疊 DataFrame (axis=0)
df_concat_row = pd.concat([df, df2], axis=0, ignore_index=True)
print("\n沿著列方向串聯後的 DataFrame:")
print(df_concat_row)
# 使用 pd.concat() 沿著欄方向堆疊 DataFrame (axis=1) - 注意 Date 欄位重複
df_concat_col = pd.concat([df, df2], axis=1)
print("\n沿著欄方向串聯後的 DataFrame:")
print(df_concat_col)
2. 資料的操作與變換
情境: 您可能需要對現有資料進行計算、轉換格式或新增欄位。
方法: Pandas 提供了豐富的 DataFrame 和 Series 操作方法。
- 欄位選取:
df['欄位名稱']
或df[['欄位名稱1', '欄位名稱2']]
- 條件篩選:
df[df['欄位名稱'] > 某值]
- 新增欄位:
df['新欄位名稱'] = 計算公式
- 函數應用:
.apply()
,.map()
,.applymap()
範例:
# 計算每日價格波動幅度 (High - Low)
df['Price_Range'] = df['High'] - df['Low']
print("新增 'Price_Range' 欄位後的 DataFrame:")
print(df)
# 將 'Volume' 欄位轉換為千股單位
df['Volume_K'] = df['Volume'] / 1000
print("\n新增 'Volume_K' 欄位後的 DataFrame:")
print(df)
# 使用 apply() 函數將 'Date' 欄位格式化為 'YYYY/MM/DD'
df['Date_Formatted'] = df['Date'].apply(lambda x: x.strftime('%Y/%m/%d'))
print("\n新增 'Date_Formatted' 欄位後的 DataFrame:")
print(df)
3. 資料的聚合與群組運算
情境: 您可能需要對資料進行分組,並計算各組的統計量 (例如平均值、總和、最大值等)。
方法: Pandas 的 groupby()
方法用於分組,並可搭配聚合函數 (例如 .mean()
, .sum()
, .max()
, .min()
, .count()
, .agg()
) 進行群組運算。
範例 (假設資料包含不同股票的資料,新增 'Stock'
欄位):
# 假設資料包含不同股票,新增 'Stock' 欄位
stock_data = {'Date': pd.to_datetime(['2024-01-01', '2024-01-02', '2024-01-01', '2024-01-02']),
'Stock': ['NVDA', 'NVDA', 'AAPL', 'AAPL'],
'Close': [120, 125, 170, 175],
'Volume': [1000, 1500, 2000, 2500]}
df_stocks = pd.DataFrame(stock_data)
print("\n包含不同股票的 DataFrame:")
print(df_stocks)
# 根據 'Stock' 欄位分組,計算各股票的平均收盤價
grouped_mean_close = df_stocks.groupby('Stock')['Close'].mean()
print("\n各股票的平均收盤價:")
print(grouped_mean_close)
# 根據 'Stock' 欄位分組,計算各股票的總成交量和最大收盤價 (使用 agg() 函數)
grouped_agg = df_stocks.groupby('Stock').agg({'Volume': 'sum', 'Close': 'max'})
print("\n各股票的總成交量和最大收盤價:")
print(grouped_agg)
4. 遺漏資料與異常值處理的基礎
- 遺漏資料 (Missing Data): 資料中某些欄位的值缺失,常見原因包括資料收集錯誤、資料損壞等。
- 異常值 (Outliers): 資料中數值明顯偏離正常範圍的值,可能是錯誤或特殊事件造成。
5. 遺漏資料的處理方法
檢查遺漏值:
.isnull()
: 判斷 DataFrame 或 Series 中的每個元素是否為遺漏值 (NaN)。.notnull()
: 與.isnull()
相反,判斷是否為非遺漏值。.isna()
:.isnull()
的別名。.notna()
:.notnull()
的別名。.isnull().sum()
: 統計每欄遺漏值的數量。.isnull().any()
: 檢查 DataFrame 是否有任何遺漏值。
處理方法:
- 刪除遺漏值:
.dropna()
: 刪除包含遺漏值的行或列。
- 填補遺漏值:
.fillna(value)
: 使用指定值填補遺漏值。.fillna(method='ffill')
: 使用前一個非遺漏值填補 (向前填補)。.fillna(method='bfill')
: 使用後一個非遺漏值填補 (向後填補)。.fillna(df.mean())
: 使用該欄的平均值填補。.fillna(df.median())
: 使用該欄的中位數填補。.fillna(df.mode())
: 使用該欄的眾數填補。
範例 (假設 df
中存在遺漏值):
# 假設 df 中存在遺漏值
df.loc[2, 'Open'] = None
df.loc[4, 'Volume'] = None
print("\n包含遺漏值的 DataFrame:")
print(df)
# 檢查每欄遺漏值數量
print("\n每欄遺漏值數量:")
print(df.isnull().sum())
# 刪除包含遺漏值的行
df_dropna = df.dropna()
print("\n刪除遺漏值後的 DataFrame:")
print(df_dropna)
# 使用 0 填補遺漏值
df_fillna_0 = df.fillna(0)
print("\n使用 0 填補遺漏值後的 DataFrame:")
print(df_fillna_0)
# 使用前一個值向前填補遺漏值
df_fillna_ffill = df.fillna(method='ffill')
print("\n向前填補遺漏值後的 DataFrame:")
print(df_fillna_ffill)
# 使用平均值填補遺漏值
df_fillna_mean = df.fillna(df.mean(numeric_only=True)) # numeric_only=True 避免對非數值欄位計算平均值
print("\n使用平均值填補遺漏值後的 DataFrame:")
print(df_fillna_mean)
6. 異常資料的處理方法
檢查異常值:
- 視覺化方法: 盒鬚圖 (Box Plot)、散佈圖 (Scatter Plot) 等。
- 統計方法: 標準差 (Standard Deviation)、Z-score、四分位距 (IQR) 等。
處理方法:
- 刪除異常值: 直接移除異常值所在的資料點。
- 替換異常值: 使用平均值、中位數、邊界值等替換異常值。
- 保留異常值: 若異常值具有實際意義,則可保留並進行特殊處理。
範例 (基於標準差判斷異常值,並替換為邊界值):
# 假設 'Close' 欄位存在異常值
df.loc[1, 'Close'] = 100 # 模擬異常值
print("\n包含異常值的 DataFrame:")
print(df)
# 計算 'Close' 欄位的平均值和標準差
mean_close = df['Close'].mean()
std_close = df['Close'].std()
# 設定異常值的上下界 (例如:平均值 +/- 3 個標準差)
lower_bound = mean_close - 3 * std_close
upper_bound = mean_close + 3 * std_close
print(f"\n收盤價正常範圍: {lower_bound:.2f} ~ {upper_bound:.2f}")
# 找出 'Close' 欄位中的異常值
outliers = df[(df['Close'] < lower_bound) | (df['Close'] > upper_bound)]
print("\n偵測到的異常值:")
print(outliers)
# 將異常值替換為邊界值
df['Close_Capped'] = df['Close'].clip(lower=lower_bound, upper=upper_bound)
print("\n異常值替換為邊界值後的 DataFrame:")
print(df)
7. 時間序列資料處理的基礎
- 時間序列資料 (Time Series Data): 以時間順序排列的資料點序列。在金融領域,股票價格、交易量等都是時間序列資料。
- Pandas 時間序列功能: Pandas 針對時間序列資料提供了強大的處理功能。
- DatetimeIndex: Pandas 使用 DatetimeIndex 作為時間序列資料的索引,方便進行時間相關的操作。
- 時間戳記 (Timestamp): 表示單一時間點。
- 時間區間 (Period): 表示一段時間範圍 (例如:日、月、年)。
- 時間間隔 (Timedelta): 表示時間長度。
範例 (將 'Date'
欄位設定為索引):
# 將 'Date' 欄位設定為 DataFrame 的索引
df_timeseries = df.set_index('Date')
print("\n將 'Date' 設定為索引的 DataFrame:")
print(df_timeseries)
# 檢查索引類型 (DatetimeIndex)
print("\n索引類型:")
print(df_timeseries.index)
8. 時間序列資料的處理與變換
- 時間序列索引操作: 利用 DatetimeIndex 可以方便地進行時間序列的選取、切片、重採樣等操作。
- 時間範圍選取:
df_timeseries['2024-01-03']
,df_timeseries['2024-01-01':'2024-01-04']
,df_timeseries['2024-01']
- 重採樣 (Resampling): 改變時間序列的頻率 (例如:將日資料轉換為週資料或月資料)。
.resample('頻率').聚合函數()
- 時間序列位移 (Shifting): 將時間序列資料向前或向後移動。
.shift(periods=n)
- 時間範圍選取:
範例:
df_timeseries = df.set_index('Date') # 確保 Date 是索引
# 選取特定日期的資料
jan_3_data = df_timeseries.loc['2024-01-03']
print("\n2024-01-03 的資料:")
print(jan_3_data)
# 選取日期範圍的資料
date_range_data = df_timeseries.loc['2024-01-01':'2024-01-04']
print("\n2024-01-01 到 2024-01-04 的資料:")
print(date_range_data)
# 將日資料重採樣為週資料,並計算每週的平均收盤價
weekly_avg_close = df_timeseries.resample('W')['Close'].mean()
print("\n週平均收盤價 (重採樣):")
print(weekly_avg_close)
# 將收盤價時間序列向前移動一天
close_shifted_forward = df_timeseries['Close'].shift(periods=1)
print("\n收盤價向前移動一天:")
print(close_shifted_forward)
# 將收盤價時間序列向後移動一天
close_shifted_backward = df_timeseries['Close'].shift(periods=-1)
print("\n收盤價向後移動一天:")
print(close_shifted_backward)
9. 移動平均 (Moving Average)
- 移動平均: 一種常用的時間序列平滑技術,用於消除短期波動,突顯長期趨勢。
- Pandas 移動平均:
.rolling(window=窗口大小).mean()
範例:
df_timeseries = df.set_index('Date') # 確保 Date 是索引
# 計算 3 日移動平均收盤價
rolling_mean_3d = df_timeseries['Close'].rolling(window=3).mean()
print("\n3 日移動平均收盤價:")
print(rolling_mean_3d)
# 計算 5 日移動平均成交量
rolling_mean_5d_volume = df_timeseries['Volume'].rolling(window=5).mean()
print("\n5 日移動平均成交量:")
print(rolling_mean_5d_volume)
總結
以上範例涵蓋了使用 Pandas 進行股票交易數據分析處理的基礎方法,包括資料結合、操作、聚合、遺漏值與異常值處理以及時間序列資料處理和移動平均。
請注意,由於我無法直接讀取您提供的 CSV 檔案,上述程式碼範例是基於簡化資料的示範。實際應用時,您需要根據您的資料集調整程式碼。
建議您可以參考 Pandas 官方文件以及網路上的 Pandas 教學資源,深入學習 Pandas 的各種功能,以便更有效地進行資料分析。
import pandas as pd
import io
import requests
# **步驟 1: 載入資料**
# 假設 CSV 檔案可以從提供的 GitHub 連結直接下載
# (Colab 可以直接讀取 URL,但如果 GitHub 限制存取,可能需要先下載到 Colab 環境)
csv_url = "[https://raw.githubusercontent.com/ranaroussi/yfinance/main/tests/data/SOLB-BR-1d-bad-div-fixed.csv](https://raw.githubusercontent.com/ranaroussi/yfinance/main/tests/data/SOLB-BR-1d-bad-div-fixed.csv)"
try:
response = requests.get(csv_url)
response.raise_for_status() # 檢查 HTTP 請求是否成功
csv_text = response.text
df = pd.read_csv(io.StringIO(csv_text)) # 使用 io.StringIO 處理字串資料
print("資料載入成功!")
except requests.exceptions.RequestException as e:
print(f"資料載入失敗,請確認網路連線或連結是否正確: {e}")
# 如果載入失敗,使用簡化的 DataFrame 進行示範
data = {'Date': pd.to_datetime(['2024-01-01', '2024-01-02', '2024-01-03', '2024-01-04', '2024-01-05', '2024-01-06', '2024-01-07', '2024-01-08', '2024-01-09', '2024-01-10']),
'Open': [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
'High': [15, 16, 17, 18, 19, 20, 21, 22, 23, 24],
'Low': [9, 10, 11, 12, 13, 14, 15, 16, 17, 18],
'Close': [12, 13, 14, 15, 16, 17, 18, 19, 20, 21],
'Volume': [100, 150, 200, 250, 300, 350, 400, 450, 500, 550],
'Dividends': [0.1, 0, 0, 0.2, 0, 0, 0.3, 0, 0, 0.4],
'Stock Splits': [1, 1, 1, 2, 1, 1, 1, 2, 1, 1]}
df = pd.DataFrame(data)
print("使用簡化資料進行示範。")
print("原始 DataFrame:")
print(df)
# **步驟 2: 資料的結合 (示範)**
# 建立第二個 DataFrame 作為示範
data2 = {'Date': pd.to_datetime(['2024-01-01', '2024-01-03', '2024-01-05', '2024-01-11']),
'Indicator': [20, 22, 24, 25]}
df2 = pd.DataFrame(data2)
# 使用 pd.merge() 根據 'Date' 欄位結合 df 和 df2 (left join,保留 df 的所有日期)
df_merged = pd.merge(df, df2, on='Date', how='left')
print("\n合併後的 DataFrame (left join):")
print(df_merged)
# **步驟 3: 資料的操作與變換**
# 計算每日價格波動幅度 (High - Low)
df_merged['Price_Range'] = df_merged['High'] - df_merged['Low']
print("\n新增 'Price_Range' 欄位後的 DataFrame:")
print(df_merged)
# 將 'Volume' 欄位轉換為千股單位
df_merged['Volume_K'] = df_merged['Volume'] / 1000
print("\n新增 'Volume_K' 欄位後的 DataFrame:")
print(df_merged)
# 使用 apply() 函數將 'Date' 欄位格式化為 'YYYY/MM/DD' (建立新欄位)
df_merged['Date_Formatted'] = df_merged['Date'].apply(lambda x: x.strftime('%Y/%m/%d'))
print("\n新增 'Date_Formatted' 欄位後的 DataFrame:")
print(df_merged)
# **步驟 4: 資料的聚合與群組運算 (示範)**
# 假設資料包含不同股票,新增 'Stock' 欄位 (僅為示範,原始資料可能不包含)
df_merged['Stock'] = 'SOLB' # 假設所有資料都是 SOLB 股票
stock_data = {'Date': pd.to_datetime(['2024-01-01', '2024-01-02', '2024-01-01', '2024-01-02']),
'Stock': ['NVDA', 'NVDA', 'AAPL', 'AAPL'],
'Close': [120, 125, 170, 175],
'Volume': [1000, 1500, 2000, 2500]}
df_stocks = pd.DataFrame(stock_data)
df_combined_stocks = pd.concat([df_merged, df_stocks], ignore_index=True) # 合併示範股票資料
print("\n包含不同股票的 DataFrame (示範合併):")
print(df_combined_stocks)
# 根據 'Stock' 欄位分組,計算各股票的平均收盤價
grouped_mean_close = df_combined_stocks.groupby('Stock')['Close'].mean()
print("\n各股票的平均收盤價:")
print(grouped_mean_close)
# 根據 'Stock' 欄位分組,計算各股票的總成交量和最大收盤價 (使用 agg() 函數)
grouped_agg = df_combined_stocks.groupby('Stock').agg({'Volume': 'sum', 'Close': 'max'})
print("\n各股票的總成交量和最大收盤價:")
print(grouped_agg)
# **步驟 5: 遺漏資料處理 (示範)**
df_missing = df_merged.copy() # 複製 DataFrame 進行遺漏值處理示範
df_missing.loc[2:4, 'Open'] = None # 模擬 'Open' 欄位遺漏值
df_missing.loc[7:9, 'Volume'] = None # 模擬 'Volume' 欄位遺漏值
print("\n包含遺漏值的 DataFrame (示範):")
print(df_missing)
# 檢查每欄遺漏值數量
print("\n每欄遺漏值數量:")
print(df_missing.isnull().sum())
# 使用 0 填補 'Open' 欄位遺漏值
df_fillna_0_open = df_missing.copy()
df_fillna_0_open['Open'] = df_fillna_0_open['Open'].fillna(0)
print("\n'Open' 欄位使用 0 填補遺漏值:")
print(df_fillna_0_open[['Date', 'Open']]) # 只顯示 Date 和 Open 欄位方便查看
# 使用前一個值向前填補 'Volume' 欄位遺漏值
df_fillna_ffill_volume = df_missing.copy()
df_fillna_ffill_volume['Volume'] = df_fillna_ffill_volume['Volume'].fillna(method='ffill')
print("\n'Volume' 欄位向前填補遺漏值:")
print(df_fillna_ffill_volume[['Date', 'Volume']]) # 只顯示 Date 和 Date 欄位方便查看
# 使用平均值填補 'Indicator' 欄位遺漏值
df_fillna_mean_indicator = df_missing.copy()
df_fillna_mean_indicator['Indicator'] = df_fillna_mean_indicator['Indicator'].fillna(df_fillna_mean_indicator['Indicator'].mean())
print("\n'Indicator' 欄位使用平均值填補遺漏值:")
print(df_fillna_mean_indicator[['Date', 'Indicator']]) # 只顯示 Date 和 Indicator 欄位方便查看
# **步驟 6: 異常值處理 (示範 - 基於 'Close' 欄位)**
df_outlier = df_merged.copy() # 複製 DataFrame 進行異常值處理示範
df_outlier.loc[5, 'Close'] = df_outlier['Close'].mean() + 5 * df_outlier['Close'].std() # 模擬 'Close' 欄位異常值 (極端值)
print("\n包含異常值的 DataFrame (示範):")
print(df_outlier[['Date', 'Close']]) # 只顯示 Date 和 Close 欄位方便查看
# 計算 'Close' 欄位的平均值和標準差
mean_close = df_outlier['Close'].mean()
std_close = df_outlier['Close'].std()
# 設定異常值的上下界 (例如:平均值 +/- 2.5 個標準差)
lower_bound = mean_close - 2.5 * std_close
upper_bound = mean_close + 2.5 * std_close
print(f"\n收盤價正常範圍 (平均值 +/- 2.5 個標準差): {lower_bound:.2f} ~ {upper_bound:.2f}")
# 將 'Close' 欄位中的異常值替換為邊界值
df_outlier['Close_Capped'] = df_outlier['Close'].clip(lower=lower_bound, upper=upper_bound)
print("\n'Close' 欄位異常值替換為邊界值:")
print(df_outlier[['Date', 'Close', 'Close_Capped']]) # 顯示 Date, Close, Close_Capped 欄位方便查看
# **步驟 7: 時間序列資料處理**
df_timeseries = df_merged.copy()
df_timeseries = df_timeseries.set_index('Date') # 將 'Date' 欄位設定為 DataFrame 的索引
print("\n將 'Date' 設定為索引的 DataFrame:")
print(df_timeseries)
# 檢查索引類型 (DatetimeIndex)
print("\n索引類型:")
print(df_timeseries.index)
# **步驟 8: 時間序列操作**
# 選取特定日期範圍的資料 (例如 2024-01-03 到 2024-01-07)
date_range_data = df_timeseries.loc['2024-01-03':'2024-01-07']
print("\n2024-01-03 到 2024-01-07 的資料:")
print(date_range_data)
# 將日資料重採樣為週資料,並計算每週的平均收盤價
weekly_avg_close = df_timeseries.resample('W')['Close'].mean()
print("\n週平均收盤價 (重採樣):")
print(weekly_avg_close)
# 將收盤價時間序列向前移動一天
close_shifted_forward = df_timeseries['Close'].shift(periods=1)
print("\n收盤價向前移動一天 (顯示 Date 和原始 Close 與位移後的 Close):")
print(pd.concat([df_timeseries['Close'], close_shifted_forward.rename('Close_Forward')], axis=1))
# **步驟 9: 移動平均**
# 計算 3 日移動平均收盤價
rolling_mean_3d = df_timeseries['Close'].rolling(window=3).mean()
print("\n3 日移動平均收盤價 (顯示 Date 和原始 Close 與 3日移動平均):")
print(pd.concat([df_timeseries['Close'], rolling_mean_3d.rename('MA_3D')], axis=1))
# 計算 5 日移動平均成交量
rolling_mean_5d_volume = df_timeseries['Volume'].rolling(window=5).mean()
print("\n5 日移動平均成交量 (顯示 Date 和原始 Volume 與 5日移動平均):")
print(pd.concat([df_timeseries['Volume'], rolling_mean_5d_volume.rename('MA_5D_Volume')], axis=1))
print("\n**程式碼執行完成!** 以上範例示範了 Pandas 在股市交易數據分析中的基本操作。")