跳至內容

pandas

本頁使用了標題或全文手工轉換
維基百科,自由的百科全書

pandas
原作者Wes McKinney英語Wes McKinney
開發者社群
首次發布2008年1月11日,​17年前​(2008-01-11
目前版本2.2.3[1]在維基數據編輯(2024年9月20日,6個月前)
原始碼庫 編輯維基數據鏈結
程式語言Python, Cython, C
作業系統跨平台
類型資料分析
許可協定三條款BSD許可證
網站pandas.pydata.org

電腦編程中,pandas是用於資料操縱分析Python軟體庫。它建造在NumPy基礎上,並為操縱數值表格時間序列,提供了資料結構和運算操作。它是在三條款BSD許可證下發行的自由軟體[2]。它的名字衍生自術語「縱橫資料」(panel data),這是計量經濟學的術語,即包括了對同一個體在某個時期內多個時間點的觀測資料集[3]。它的名字還可解釋為對短語「Python data analysis」的玩笑[4]

歷史

[編輯]

2008年,原作者Wes McKinney英語Wes McKinney開始在AQR資本管理公司製作pandas,用來滿足在財務資料上進行定量分析英語Quantitative analysis (finance)時,對高效能、靈活工具的需要。2009年,他在離開AQR之前,說服管理者允許他將這個軟體庫開放原始碼。下面是其開發過程的時間線[5]

  • 2008年,pandas開發開始。
  • 2009年,pandas開源。
  • 2012年,另一個AQR雇員Chang She加入了這個專案,並成為這個軟體庫的第二個主要貢獻者。第一版《Python for Data Analysis》發布。
  • 2015年,pandas簽約為NumFOCUS的一個財務贊助專案,NumFOCUS是美國的501(c)(3)非營利公益組織
  • 2018年,舉行了第一次面對面的「核心開發者衝刺」。
  • 2022年,第三版《Python for Data Analysis》公開版線上發行[6]

資料模型

[編輯]

pandas的序列Series)是一維加標籤資料結構,它能夠持有任何資料類型,如整數、字串、浮點數和Python對象等,標籤在集體上稱為索引(index)。序列表現得非常類似於NumPyndarray資料結構,並且是大多數NumPy函式的有效實際參數。

pandas提供了類似於R語言中data.frame對象的資料訊框(DataFrame),它是二維加標籤資料結構,其諸縱列潛在的可能具有不同的類型;資料訊框就像是電子試算表SQL,或者是序列字典[7],這種格局也叫做陣列之結構英語AoS_and_SoA(SoA)。pandas允許各種資料操縱運算操作,比如選擇[8]、合併[9]和重製形狀[10],還有資料淨化資料加工英語data wrangling特徵。

主要特徵

[編輯]

pandas提供了快速而高效的資料訊框對象,用於憑藉其整合的索引進行資料操縱。它的主要特徵有:

  • 易於將在其他的Python和NumPy資料結構中,參差不齊或不同索引的資料,轉換成資料訊框對象。
  • 大小可變性,可以在資料訊框和更高維對象中插入或刪除縱列
  • 自動和顯式的「資料對齊」,標籤和資料之間的聯絡是原生的,但是可以顯式的控制二元運算的匹配和廣播行為[11]。兩個序列對象按標籤自動對齊,兩個資料訊框對象自動對齊於縱列標籤和索引(即橫行標籤)二者上,二元運算的結果對象具有雙方的縱列標籤和橫行標籤的併集;資料訊框與序列對象之間的預設行為,是序列的索引自動對齊於資料訊框的縱列標籤,從而縱向逐橫行廣播[12]
  • 易於處理缺失資料,它被表示為用於浮點數NaN(即NumPy的nan)、用於日期時間的NaT或跨資料類型的NA[13]
  • 智慧型的對巨量資料集的基於標籤的分片英語Array slicing,多重索引和其他花樣索引,依據布林值向量的子集化英語Subsetting
  • 直觀的資料集的合併和連接
  • 強大而靈活的分組英語Group by (SQL)groupby)功能,用來在資料集上進行分離-應用-合併(split-apply-combine)運算,它可用於資料聚合英語Aggregate function變換英語Data transformation (computing)二者。
  • 靈活的資料集的重製形狀(reshape)和樞軸匯總
  • 可以有層級標籤,從而在繪圖時每個刻度可能有多重標籤。
  • 健壯的I/O工具,用於從CSV檔案和其他平面檔案JSON檔案、Parquet英語Apache Parquet檔案、Arrow的Feather檔案、SQL查詢Excel檔案裝載資料,並以極快的HDF5格式儲存/裝載資料。[14]
  • 特定於時間序列的功能,例如日期範圍生成和頻率轉換,移動窗口統計比如移動平均,日期移位英語Shift operator滯後英語Lag operator

pandas經過了高度的效能最佳化,關鍵代碼路徑用CythonC語言寫成。pandas可以利用PyArrow來擴充功能並增進各種API的效能[15]。pandas的預設繪圖後端是matplotlib,還可以擴充上其他第三方繪圖英語Plot (graphics)後端[16],比如Plotly Express[17]行程內英語Embedded databaseSQL OLAP列式資料庫DuckDB,可以在pandas資料訊框上執行SQL[18]

範例

[編輯]

基本運算

[編輯]

在下面的梗概範例中,展示針對資料訊框的縱列橫行的基本運算:

>>> import pandas as pd
>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> 
>>> data = {
...     'place': ['A']*3 + ['B']*3 + ['C']*3 + ['D']*3,
...     'date': pd.to_datetime(['2023-01-01', '2023-01-02', '2023-01-03'] * 4),
...     'value': [x + 0.1 for x in range(12)]
... }
>>> 
>>> df = pd.DataFrame(data)
>>> type(df['value']) == pd.Series
True
>>>
>>> df['value1'] = df['value'] + 0.1
>>> df
   place       date  value  value1
0      A 2023-01-01    0.1     0.2
1      A 2023-01-02    1.1     1.2
2      A 2023-01-03    2.1     2.2
3      B 2023-01-01    3.1     3.2
4      B 2023-01-02    4.1     4.2
5      B 2023-01-03    5.1     5.2
6      C 2023-01-01    6.1     6.2
7      C 2023-01-02    7.1     7.2
8      C 2023-01-03    8.1     8.2
9      D 2023-01-01    9.1     9.2
10     D 2023-01-02   10.1    10.2
11     D 2023-01-03   11.1    11.2
>>> 
>>> df.index
RangeIndex(start=0, stop=12, step=1)
>>> 
>>> df.columns
Index(['place', 'date', 'value', 'value1'], dtype='object')
>>> 
>>> df.loc[[1, 2], ['value', 'value1']] 
   value  value1
1    1.1     1.2
2    2.1     2.2
>>> 
>>> df.at[1, 'value']
1.1
>>> 
>>> df['value'].loc[1]
1.1
>>> 
>>> df[['value','value1']].to_numpy().mean().round(2)
np.float64(5.65)
>>> df[['value','value1']].to_numpy().mean(axis=0)
array([5.6, 5.7])
>>> df[['value','value1']].to_numpy().mean(axis=1)
array([ 0.15,  1.15,  2.15,  3.15,  4.15,  5.15,  6.15,  7.15,  8.15,
        9.15, 10.15, 11.15])
>>> 
>>> df[(df['value']/2 > 1) & (df['value1'] < 3)]
  place       date  value  value1
2     A 2023-01-03    2.1     2.2
>>> 
>>> df.query('value/2 > 1 & value1 < 3')
  place       date  value  value1
2     A 2023-01-03    2.1     2.2
>>>
>>> df[df['value'] == 1.1]['value1'].round(2).item()
1.2
>>>

資料訊框格式

[編輯]

資料訊框中的資料經常儲存為兩種格式堆疊(stack)格式或記錄(record)格式。在堆疊格式中,針對每個主題(subject)在適用情況下有多個橫行,故而也稱為「長」格式。在記錄格式中,針對每個主題典型地有一個橫行,故而也稱為「寬」格式。在這個例子中,如果要對縱列'place'標識出的每個唯一的變數('A', 'B', 'C', 'D')進行時間序列運算,更好的表示形式為:諸縱列都對應唯一的變數,即對應不同的觀測地點或觀測者,而日期索引('date')標識出每個(不可細分的)個體觀測。為此使用pivot(),將資料訊框從堆疊格式重製形狀為記錄格式:

>>> df.drop([0, 4, 8]).pivot(index='date', columns='place')
           value                 value1                
place          A    B    C     D      A    B    C     D
date                                                   
2023-01-01   NaN  3.1  6.1   9.1    NaN  3.2  6.2   9.2
2023-01-02   1.1  NaN  7.1  10.1    1.2  NaN  7.2  10.2
2023-01-03   2.1  5.1  NaN  11.1    2.2  5.2  NaN  11.2
>>>

這裡刪除了三個橫行展示了NaN被用來表示缺失資料。這裡在pivot()的輸入資料訊框的諸縱列中,通過index參數指定了用作索引的縱列('date'),通過columns參數指定了用作變數的縱列('place'),但沒有通過指定values參數於多個值縱列('value', 'value1')里選取其中之一,故而結果資料訊框的諸縱列被納入層級式索引(即多重索引MultiIndex),其最頂層指示出各自的值縱列,即依據觀測的不同而進行頂層分組。

串接運算

[編輯]

使用concat()對資料訊框進行串接英語Set operations (SQL)運算:

>>> df1 = df.drop(columns='value').rename(columns={'value1': 'value'})
>>> df1 = pd.concat([df.drop(columns='value1'), df1], ignore_index=True)
>>> df1.shape
(24, 3)
>>> 
>>> data1 = [
...     ('A', pd.to_datetime('2023-01-01'), 0.3),
...     ('A', pd.to_datetime('2023-01-02'), 1.3)
... ]
>>> 
>>> new_rows = pd.DataFrame(data1, columns=['place', 'date', 'value'])
>>> pd.concat([df1, new_rows], ignore_index=True).tail(3)
   place       date  value
23     D 2023-01-03   11.2
24     A 2023-01-01    0.3
25     A 2023-01-02    1.3
>>> 
>>> df_A = df1[df1['place']=='A'].drop(columns='place')
>>> df_A
         date  value
0  2023-01-01    0.1
1  2023-01-02    1.1
2  2023-01-03    2.1
12 2023-01-01    0.2
13 2023-01-02    1.2
14 2023-01-03    2.2
>>> 
>>> df_B = df1[df1['place']=='B'].drop(columns='place')
>>> df_C = df1[df1['place']=='C'].drop(columns='place')
>>> df_D = df1[df1['place']=='D'].drop(columns='place')
>>> df1 = pd.concat([df_A, df_B, df_C, df_D], keys=['A', 'B', 'C', 'D']) \
...     .droplevel(1).rename_axis('place').reset_index()
>>>

分組聚合運算

[編輯]

使用groupby()和緊隨其後的agg(),對資料訊框進行分組英語Group by (SQL)聚合英語Aggregate function運算:

>>> df2 = df1.groupby(['date', 'place']).agg({'value': 'sum'})
>>> df2
                  value
date       place       
2023-01-01 A        0.3
           B        6.3
           C       12.3
           D       18.3
2023-01-02 A        2.3
           B        8.3
           C       14.3
           D       20.3
2023-01-03 A        4.3
           B       10.3
           C       16.3
           D       22.3
>>> 
>>> df2.reorder_levels(['place', 'date']).sort_index()
                  value
place date             
A     2023-01-01    0.3
      2023-01-02    2.3
      2023-01-03    4.3
B     2023-01-01    6.3
      2023-01-02    8.3
      2023-01-03   10.3
C     2023-01-01   12.3
      2023-01-02   14.3
      2023-01-03   16.3
D     2023-01-01   18.3
      2023-01-02   20.3
      2023-01-03   22.3
>>> 
>>> df2.shape
(12, 1)
>>> 
>>> df2.index
MultiIndex([('2023-01-01', 'A'),
            ('2023-01-01', 'B'),
            ('2023-01-01', 'C'),
            ('2023-01-01', 'D'),
            ('2023-01-02', 'A'),
            ('2023-01-02', 'B'),
            ('2023-01-02', 'C'),
            ('2023-01-02', 'D'),
            ('2023-01-03', 'A'),
            ('2023-01-03', 'B'),
            ('2023-01-03', 'C'),
            ('2023-01-03', 'D')],
           names=['date', 'place'])
>>> 
>>> df2.columns
Index(['value'], dtype='object')
>>> 
>>> df2.loc[('2023-01-02', 'A')]
value    2.3
Name: (2023-01-02 00:00:00, A), dtype: float64
>>> 
>>> df2.loc['2023-01-02']
       value
place       
A        2.3
B        8.3
C       14.3
D       20.3
>>> 
>>> df2.xs('A', level='place')
            value
date             
2023-01-01    0.3
2023-01-02    2.3
2023-01-03    4.3
>>>

樞軸聚合運算

[編輯]

使用pivot_table(),對資料訊框進行樞軸聚合運算:

>>> df3 = df1.pivot_table(index='date', columns='place', aggfunc='sum')
>>> df3
           value                  
place          A     B     C     D
date                              
2023-01-01   0.3   6.3  12.3  18.3
2023-01-02   2.3   8.3  14.3  20.3
2023-01-03   4.3  10.3  16.3  22.3
>>> 
>>> df3.shape
(3, 4)
>>> 
>>> df3.to_numpy()
array([[ 0.3,  6.3, 12.3, 18.3],
       [ 2.3,  8.3, 14.3, 20.3],
       [ 4.3, 10.3, 16.3, 22.3]])
>>> 
>>> df3.index
DatetimeIndex(['2023-01-01', '2023-01-02', '2023-01-03'], dtype='datetime64[ns]', name='date', freq=None)
>>> 
>>> df3.columns
MultiIndex([('value', 'A'),
            ('value', 'B'),
            ('value', 'C'),
            ('value', 'D')],
           names=[None, 'place'])
>>> 
>>> df1.pivot_table(index='date', columns='place', values='value', aggfunc='sum').columns
Index(['A', 'B', 'C', 'D'], dtype='object', name='place')
>>> 
>>> df3['value'].columns
Index(['A', 'B', 'C', 'D'], dtype='object', name='place')
>>> 
>>> df3[('value', 'A')]
date
2023-01-01    0.3
2023-01-02    2.3
2023-01-03    4.3
Name: (value, A), dtype: float64
>>> 
>>> df3.stack().shape
(12, 1)
>>> df2.unstack().shape
(3, 4)
>>>

合併運算

[編輯]

使用merge(),對資料訊框進行合併運算:

>>> sr_A = df3[('value', 'A')]
>>> sr_B = df3[('value', 'B')]
>>> sr_C = df3[('value', 'C')]
>>> sr_D = df3[('value', 'D')]
>>> merge_date = lambda x, y: pd.merge(x, y, on='date')
>>> df3 = merge_date(merge_date(sr_A, sr_B), merge_date(sr_C, sr_D)) \
...     .rename_axis([None, 'place'], axis=1)
>>> 
>>> pd.merge(df_A, df_B.drop('2023-01-02'), on='date')
           value      
               A     B
date                  
2023-01-01   0.3   6.3
2023-01-03   4.3  10.3
>>> 
>>> pd.merge(df_A, df_B.drop('2023-01-02'), on='date', how='left')
           value      
               A     B
date                  
2023-01-01   0.3   6.3
2023-01-02   2.3   NaN
2023-01-03   4.3  10.3
>>>

繪圖輸出

[編輯]
例子代碼生成的條形圖。

matplotlib為資料訊框繪製條形圖

>>> df_axis0, df_axis1 = df3.shape
>>> df_columns = df3.to_dict(orient='list')
>>> df_index = df3.index.to_list()
>>> x = np.arange(df_axis0)
>>> width = 1/(df_axis1 + 1)
>>> mult = 0
>>> 
>>> fig, ax = plt.subplots(layout='constrained')
>>> for name, value in df_columns.items():
...     offset = width * mult
...     rects = ax.bar(x + offset, value, width, label=name[1])
...     ax.bar_label(rects, padding=3)
...     mult += 1
... 
[Text(0, 3, '0.3'), Text(0, 3, '2.3'), Text(0, 3, '4.3')]
[Text(0, 3, '6.3'), Text(0, 3, '8.3'), Text(0, 3, '10.3')]
[Text(0, 3, '12.3'), Text(0, 3, '14.3'), Text(0, 3, '16.3')]
[Text(0, 3, '18.3'), Text(0, 3, '20.3'), Text(0, 3, '22.3')]
>>> ax.set_xticks(x + width*(df_axis1 - 1)/2,
...     [x.strftime('%Y-%m-%d') for x in df_index])
[<matplotlib.axis.XTick object at 0x7bb6925408f0>, <matplotlib.axis.XTick object at 0x7bb692541700>, <matplotlib.axis.XTick object at 0x7bb6925421e0>]
>>> ax.legend()
<matplotlib.legend.Legend object at 0x7bb696123aa0>
>>> ax.grid(axis='y', linestyle=':')
>>> ax.set_axisbelow(True)
>>> plt.show()
>>>

CSV檔案操作

[編輯]

匯出和匯入CSV檔案:

>>> df2.to_csv('dftest.csv', float_format='%.1f')
>>> 
>>> df4 = pd.read_csv('dftest.csv', index_col=[0,1])
>>> df4.shape
(12, 1)

在不指定header參數即採用其預設值之時,從匯入檔案檔頭即第一橫行推導出資料的縱列名字。在匯入檔案時採用index_col參數,指定用作索引即橫行標籤的縱列。在檔頭的縱列數大於資料記錄的縱列數之時,檔頭末位多出的縱列被設定為NaN;在檔頭的縱列數小於資料記錄的縱列數之時,資料記錄首位多出的縱列被用作索引;在檔頭的縱列數等於資料記錄的縱列數,並且未指定索引列之時,則自動增加預設的沒有名字的範圍索引作為索引;在檔頭的縱列數等於資料記錄的縱列數,並且已指定索引列之時,採用指定縱列作為索引。

在匯入檔案時可以通過usecols參數指定選用的縱列子集。如果所匯入的檔案沒有檔頭,則需要指定header=None,還可以使用names參數,為匯入資料指定縱列名字。如果所匯入的檔案有檔頭,並且要使用names參數指定替代它的縱列名字,則需要同時指定header=0。在匯出檔案時索引總是被匯出的,可以使用index_label參數,為沒有名字的索引縱列補充指定其名字。在匯入pandas所匯出的檔案之時,需要指定索引列來避免再次自動增加預設索引。

當資料訊框是記錄格式,故而columns方向採用了多重索引之時,所匯出的CSV檔案的檔頭有多個橫行,以這裡的資料訊框df3為例,在匯入它之時需要指定header=[0, 1]index_col=0,但不能同時使用usecolsnames參數:

>>> df3.to_csv('dftest.csv', float_format='%.1f')
>>> 
>>> df4 = pd.read_csv('dftest.csv', header=[0, 1], index_col=0)
>>> df4.shape
(3, 4)

使用util-linux工具組成員column來檢視匯出的CSV檔案:

$ cat dftest.csv | column -s, -o, -t 
          ,value,value,value,value
place     ,A    ,B    ,C    ,D
date      ,     ,     ,     ,
2023-01-01,0.3  ,6.3  ,12.3 ,18.3
2023-01-02,2.3  ,8.3  ,14.3 ,20.3
2023-01-03,4.3  ,10.3 ,16.3 ,22.3

這裡的前兩橫行的除了第一縱列之外的縱列,指定多層索引的縱列名字為[('value', 'A'), ('value', 'B'), ('value', 'C'), ('value', 'D')]。第一縱列的前兩單元,指定了諸縱列columns的多重索引自身的名字列表為[None, 'place'],而第一縱列的第三單元,指定了索引index的日期時間索引自身的名字為'date'

JSON檔案操作

[編輯]

匯出和匯入JSON檔案:

>>> df3.to_json('dftest.json', orient='index', date_format='iso', date_unit='s')
>>> 
>>> df4 = pd.read_json('dftest.json', orient='index')
>>> df4.shape
(3, 4)
>>> 
>>> df4.columns
Index(['('value', 'A')', '('value', 'B')', '('value', 'C')', '('value', 'D')'], dtype='object')
>>> 
>>> df4.columns = pd.MultiIndex.from_tuples([eval(x) for x in df4.columns])
>>> df4.columns.names = [None, 'place']
>>> df4.index.name = 'date'

這裡指定了orient(方向)為'index'(索引),即採用橫行為主英語Row- and column-major order次序;這裡指定了日期時間格式為ISO 8601標準格式,並且指定了時間單位。JSON對象的鍵只能是字串,在匯出為JSON檔案之時,元組被轉換成字串;而在匯入它之時,需要通過eval()將其再轉換為元組。

使用jq語言實現jq來檢視匯出的JSON檔案:

$ cat dftest.json | jq
{
  "2023-01-01T00:00:00": {
    "('value', 'A')": 0.3,
    "('value', 'B')": 6.3,
    "('value', 'C')": 12.3,
    "('value', 'D')": 18.3
  },
  "2023-01-02T00:00:00": {
    "('value', 'A')": 2.3,
    "('value', 'B')": 8.3,
    "('value', 'C')": 14.3,
    "('value', 'D')": 20.3
  },
  "2023-01-03T00:00:00": {
    "('value', 'A')": 4.3,
    "('value', 'B')": 10.3,
    "('value', 'C')": 16.3,
    "('value', 'D')": 22.3
  }
}

在匯出的資料中,不包含諸縱列columns的多重索引自身的名字列表即[None, 'place'],不包含索引index自身的名字即'date'

HDF5檔案操作

[編輯]

匯出和匯入HDF5檔案基於了PyTables[19]

>>> df3.to_hdf('dftest.h5', key='df3', mode='w')
>>> df.to_hdf('dftest.h5', key='df', mode='a')
>>> 
>>> df4 = pd.read_hdf('dftest.h5', key='df3')
>>> df4.shape
(3, 4)

這裡通過key)參數,指定了與資料訊框相對應的在HDF5檔案中的群組(Group),對它採用了預設的'fixed'(固定)儲存格式。檔案打開模態'w'是為「寫」(write)即「新建」,而打開模態'a'是為「附加」(append)。

使用hdf5-tools工具組成員h5ls來檢視匯出的HDF5檔案:

$ h5ls dftest.h5
df                       Group
df3                      Group
$ h5ls -r -d dftest.h5/df3
/axis0_label0            Dataset {4}
    Data:
         0, 0, 0, 0
/axis0_label1            Dataset {4}
    Data:
         0, 1, 2, 3
/axis0_level0            Dataset {1}
    Data:
         "value"
/axis0_level1            Dataset {4}
    Data:
         "A", "B", "C", "D"
/axis1                   Dataset {3}
    Data:
         1672531200000000000, 1672617600000000000, 1672704000000000000
/block0_items_label0     Dataset {4}
    Data:
         0, 0, 0, 0
/block0_items_label1     Dataset {4}
    Data:
         0, 1, 2, 3
/block0_items_level0     Dataset {1}
    Data:
         "value"
/block0_items_level1     Dataset {4}
    Data:
         "A", "B", "C", "D"
/block0_values           Dataset {3, 4}
    Data:
         0.3, 6.3, 12.3, 18.3, 2.3, 8.3, 14.3, 20.3, 4.3, 10.3, 16.3, 22.3

這裡的HDF5檔案中的日期時間表示,是以奈秒單位UNIX時間紀元英語Epoch (computing)時間戳。這種儲存格式儲存了資料訊框的兩個和所有的塊[20],它採用的軸編號01與編程API所用的NumPy軸編號相反[21]。這裡的df3儲存只有一個塊,這個塊的items的內容同於axis0。下面檢視df儲存的情況,它的四個縱列被整合(consolidate)為三個塊,其items併集同於axis0:

$ h5ls -r dftest.h5/df
/axis0                   Dataset {4}
/axis1                   Dataset {12}
/block0_items            Dataset {1}
/block0_values           Dataset {12, 1}
/block1_items            Dataset {2}
/block1_values           Dataset {12, 2}
/block2_items            Dataset {1}
/block2_values           Dataset {1/Inf}

儲存HDF5檔案還可採用'table'(表格)格式,HDF5檔案中這種儲存格式的群組,可以直接在其上進行查詢和過濾:

>>> df3.to_hdf('dftest.h5', key='df3t', format='table', mode='a')
>>> 
>>> pd.read_hdf('dftest.h5', key='df3t', where='index > 20230101', columns=[('value', 'A'), ('value', 'C')])
           value      
place          A     C
date                  
2023-01-02   2.3  14.3
2023-01-03   4.3  16.3

檢視HDF5檔案中的這種儲存格式:

$ h5ls dftest.h5/df3t
_i_table                 Group
table                    Dataset {3/Inf}
$ h5ls -r -d dftest.h5/df3t/table
df4/table                Dataset {3/Inf}
    Data:
         {1672531200000000000, [0.3,6.3,12.3,18.3]},
         {1672617600000000000, [2.3,8.3,14.3,20.3]},
         {1672704000000000000, [4.3,10.3,16.3,22.3]}

這裡的_i_table/index群組儲存了PyTables的tables.index模組所存取的諸多內容[22]

netCDF檔案操作

[編輯]

匯出和匯入netCDF檔案可以藉助xarray,它依賴於pandas,它通過netcdf4-python支援匯入匯出netCDF-4格式資料[23],通過SciPy支援其他版本netCDF格式。xarray能夠在自身的資料陣列(DataArray)與pandas的序列之間,在自身的資料集(Dataset)與pandas的資料訊框之間,進行相互轉換[24]

>>> import xarray as xr
>>> 
>>> df2.to_xarray()
<xarray.Dataset> Size: 152B
Dimensions:  (date: 3, place: 4)
Coordinates:
  * date     (date) datetime64[ns] 24B 2023-01-01 2023-01-02 2023-01-03
  * place    (place) object 32B 'A' 'B' 'C' 'D'
Data variables:
    value    (date, place) float64 96B 0.3 6.3 12.3 18.3 ... 4.3 10.3 16.3 22.3
>>> 
>>> df3.to_xarray()
<xarray.Dataset> Size: 120B
Dimensions:         (date: 3)
Coordinates:
  * date            (date) datetime64[ns] 24B 2023-01-01 2023-01-02 2023-01-03
Data variables:
    ('value', 'A')  (date) float64 24B 0.3 2.3 4.3
    ('value', 'B')  (date) float64 24B 6.3 8.3 10.3
    ('value', 'C')  (date) float64 24B 12.3 14.3 16.3
    ('value', 'D')  (date) float64 24B 18.3 20.3 22.3
>>> 
>>> df2.to_xarray().to_netcdf('dftest.nc')
>>> 
>>> df4 = xr.open_dataset('dftest.nc').to_dataframe()
>>> df4.shape
(12, 1)

這裡的從堆疊格式的資料訊框df2轉換出來的資料集可以匯出至netCDF檔案,而從記錄格式的資料訊框df3轉換出來的資料集因變數名字而不能直接匯出至netCDF檔案。

使用netcdf-bin工具組成員ncdump來檢視匯出的netCDF檔案:

$ ncdump dftest.nc
netcdf dftest {
dimensions:
	date = 3 ;
	place = 4 ;
variables:
	double value(date, place) ;
		value:_FillValue = NaN ;
	int64 date(date) ;
		date:units = "days since 2023-01-01 00:00:00" ;
		date:calendar = "proleptic_gregorian" ;
	string place(place) ;
data:

 value =
  0.3, 6.3, 12.3, 18.3,
  2.3, 8.3, 14.3, 20.3,
  4.3, 10.3, 16.3, 22.3 ;

 date = 0, 1, 2 ;

 place = "A", "B", "C", "D" ;
}
$ ncdump -k dftest.nc
netCDF-4
$ h5ls -r -d dftest.nc
/                        Group
/date                    Dataset {3}
    Data:
         0, 1, 2
/place                   Dataset {4}
    Data:
         "A", "B", "C", "D"
/value                   Dataset {3, 4}
    Data:
         0.3, 6.3, 12.3, 18.3, 2.3, 8.3, 14.3, 20.3, 4.3, 10.3, 16.3, 22.3

這裡的日期時間表示遵循了氣候和預報元資料約定英語Climate and Forecast Metadata Conventions[25],採用的時間單位為距離某個指定的開始日期時間的日數曆法前推格里高利曆ncdump的輸出所稱謂的變數,代表相同類型的值的多維陣列。這裡有三個變數:value是資料變數,dateplace坐標變數。變數聲明指定了變數的資料類型、名字和以維度名字列表描述的形狀,例如double value(date, place),維度名字可以是x, y, z, t等等,而這裡的維度名字同於對應的坐標變數名字。

SQL關聯式資料庫操作

[編輯]

下面通過SQLAlchemy將資料訊框匯出和匯入於SQL關聯式資料庫SQLite

>>> from sqlalchemy import create_engine
>>> engine = create_engine("sqlite:///dftest.db")
>>> 
>>> df2.to_sql(name='df2', con=engine)
12
>>> 
>>> with engine.connect() as conn:
...     df4 = pd.read_sql('SELECT * FROM df2', conn)
... 
>>> 
>>> df4.shape
(12, 3)
>>> df4['date'] = pd.to_datetime(df4['date'])
>>> df4 = df4.set_index(['date', 'place'])
>>> df4.shape
(12, 1)

使用SQLite的命令列介面來檢視匯出的資料庫檔案:

$ echo '.tables' | sqlite3 dftest.db
df2
$ echo '.schema df2' | sqlite3 dftest.db
CREATE TABLE df2 (
	date DATETIME, 
	place TEXT, 
	value FLOAT
);
CREATE INDEX ix_df2_date ON df2 (date);
CREATE INDEX ix_df2_place ON df2 (place);
$ echo 'SELECT * FROM df2' | sqlite3 dftest.db
2023-01-01 00:00:00.000000|A|0.3
2023-01-01 00:00:00.000000|B|6.3
2023-01-01 00:00:00.000000|C|12.3
2023-01-01 00:00:00.000000|D|18.3
2023-01-02 00:00:00.000000|A|2.3
2023-01-02 00:00:00.000000|B|8.3
2023-01-02 00:00:00.000000|C|14.3
2023-01-02 00:00:00.000000|D|20.3
2023-01-03 00:00:00.000000|A|4.3
2023-01-03 00:00:00.000000|B|10.3
2023-01-03 00:00:00.000000|C|16.3
2023-01-03 00:00:00.000000|D|22.3

SQLite將SQL資料類型DATETIME硬性指定為親和NUMERIC,而NUMERIC可以按其適合情況轉換為五個儲存類別(NULLINTEGERREALTEXTBLOB)之一,這裡的資料訊框df2date縱列中的資料,被轉換成為INTEGERREALTEXT三者中的TEXT即文字字串。

參見

[編輯]

參照

[編輯]
  1. ^ 1.0 1.1 Release 2.2.3. 2024年9月20日 [2024年9月22日]. 
  2. ^ License – Package overview – pandas 1.0.0 documentation. pandas. 28 January 2020 [30 January 2020]. (原始內容存檔於2012-02-14). 
  3. ^ Wes McKinney. pandas: a Foundational Python Library for Data Analysis and Statistics (PDF). 2011 [2 August 2018]. (原始內容存檔 (PDF)於2015-05-13). The library’s name derives from panel data, a common term for multidimensional data sets encountered in statistics and econometrics. 
  4. ^ McKinney, Wes. Python for Data Analysis, Second Edition. O'Reilly Media. 2017: 13. ISBN 9781491957660. 
  5. ^ About pandas — History of development — Timeline. [2023-09-30]. (原始內容存檔於2023-10-10). 
  6. ^ Python for Data Analysis, 3E. [2023-10-06]. (原始內容存檔於2023-11-07). 
  7. ^ DataFrame. [2022-09-01]. (原始內容存檔於2022-09-01). 
  8. ^ Indexing and selecting data. [2020-09-12]. (原始內容存檔於2020-09-15). 
  9. ^ Merge, join, concatenate and compare. [2020-09-12]. (原始內容存檔於2020-09-15). 
  10. ^ Reshaping and pivot tables. [2020-09-12]. (原始內容存檔於2020-09-15). 
  11. ^ Essential basic functionality — Matching / broadcasting behavior. [2023-12-22]. (原始內容存檔於2024-04-21). 
  12. ^ Intro to data structures — Data alignment and arithmetic. [2023-12-22]. (原始內容存檔於2022-09-01). 
  13. ^ Working with missing data. [2023-12-22]. (原始內容存檔於2024-05-16). 
  14. ^ IO tools (text, CSV, HDF5, …). [2020-09-12]. (原始內容存檔於2020-09-15). 
  15. ^ McKinney, Wes. Apache Arrow and the "10 Things I Hate About pandas". wesmckinney.com. 21 September 2017 [21 December 2023]. (原始內容存檔於2024-05-25) (英語). 
  16. ^ Python tools for data visualization — High-level tools. [2023-09-28]. (原始內容存檔於2023-09-28). 
  17. ^ Pandas Plotting Backend in Python. [2024-09-24]. (原始內容存檔於2025-01-28). 
  18. ^ DuckDB Guides — SQL on Pandas. [2023-09-29]. (原始內容存檔於2023-10-03). 
  19. ^ PyTables: hierarchical datasets in Python. [2023-09-28]. (原始內容存檔於2023-08-24). 
  20. ^ Internal Structure of Pandas DataFrames. [2023-12-25]. (原始內容存檔於2023-12-25). 
  21. ^ NumPy glossary. 
  22. ^ Source code for tables.index. [2023-12-25]. (原始內容存檔於2023-12-25). 
  23. ^ netcdf4-python: Python/numpy interface to the netCDF C library. [2023-10-07]. (原始內容存檔於2023-10-12). 
  24. ^ xarray User Guide - Working with pandas. [2022-09-04]. (原始內容存檔於2022-09-04). 
  25. ^ NetCDF Climate and Forecast (CF) Metadata Conventions — Time Coordinate. [2023-10-09]. (原始內容存檔於2023-10-12). 
    xarray User Guide — Weather and climate data. [2023-10-09]. (原始內容存檔於2023-10-12). 

延伸閱讀

[編輯]

外部連結

[編輯]