在计算机编程中,pandas是用于数据操纵和分析的Python软件库。它建造在NumPy基础上,并为操纵数值表格和时间序列,提供了数据结构和运算操作。它是在三条款BSD许可证下发行的自由软件。它的名字衍生自术语“面板数据”(panel data),这是计量经济学的术语,即包括了对同一个体在某个时期内多个时间点的观测的数据集。它的名字还可解释为对短语“Python data analysis”的玩笑。
历史
2008年,原作者开始在AQR资本管理公司制作pandas,用来满足在财务数据上进行时,对高性能、灵活工具的需要。2009年,他在离开AQR之前,说服管理者允许他将这个软件库开放源代码。下面是其开发过程的时间线:
*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》公开版在线发行。
数据模型
pandas的序列(Series)是一维的加标签数据结构,它能够持有任何数据类型,如整数、字符串、浮点数和Python对象等,轴标签在集体上称为索引(index)。序列表现得非常类似于NumPy的ndarray数据结构,并且是大多数NumPy函数的有效实际参数。
pandas提供了类似于R语言中data.frame对象的数据帧(DataFrame),它是二维的加标签数据结构,其诸纵列潜在的可能具有不同的类型;数据帧就像是电子表格或SQL表,或者是序列的字典,这种格局也叫做(SoA)。pandas允许各种数据操纵运算操作,比如选择、归并和重制形状,还有数据清洗和特征。
主要特征
pandas提供了快速而高效的数据帧对象,用于凭借其集成的索引进行数据操纵。它的主要特征有:
*易于将在其他的Python和NumPy数据结构中,参差不齐或不同索引的数据,转换成数据帧对象。
*大小可变性,可以在数据帧和更高维对象中插入或删除纵列。
*自动和显式的“数据对齐”,标签和数据之间的联系是固有的,但是可以显式的控制二元运算的匹配和广播行为。两个序列对象按标签自动对齐,两个数据帧对象自动对齐于纵列标签和索引(即横行标签)二者上,二元运算的结果对象具有双方的纵列标签和横行标签的并集;数据帧与序列对象之间的默认行为,是序列的索引自动对齐于数据帧的纵列标签,从而纵向逐横行广播。
*易于处理缺失数据,它被表示为用于浮点数的NaN(即NumPy的nan)、用于日期时间的NaT或跨数据类型的NA。
*智能的对大数据集的基于标签的,多重索引和其他花样索引,依据布尔值向量的。
*直观的数据集的归并和连接。
*强大而灵活的(groupby)功能,用来在数据集上进行分离-应用-合并(split-apply-combine)运算,它可用于数据和二者。
*灵活的数据集的重制形状(reshape)和枢轴汇总。
*轴可以有层级标签,从而在绘图时每个刻度可能有多重标签。
*健壮的I/O工具,用于从CSV文件和其他平面文件、JSON文件、文件、Arrow的Feather文件、SQL表和查询、Excel文件装载数据,并以极快的HDF5格式保存/装载数据。
*特定于时间序列的功能,例如日期范围生成和频率转换,移动窗口统计比如移动平均,日期和。
pandas经过了高度的性能优化,关键代码路径用Cython或C语言写成。pandas可以利用PyArrow来扩展功能并增进各种API的性能。pandas的缺省绘图后端是matplotlib,还可以扩展上其他第三方后端,比如Plotly Express。
SQL OLAP列式数据库DuckDB,可以在pandas数据帧上执行SQL。
示例
基本运算
在下面的梗概示例中,展示针对数据帧的纵列和横行的基本运算:
>> 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'] >>
>>> df.query('value/2 > 1 & value1 >>
>>> 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()对数据帧进行运算:
>> 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(),对数据帧进行并运算:
>> 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])
[, , ]
>>> ax.legend()
>> 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,但不能同时使用usecols或names参数:
>> 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'(索引),即采用次序;这里指定了日期时间格式为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:
>> 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时间的时间戳。这种存储格式保存了数据帧的两个轴和所有的块,它采用的轴编号0和1与编程API所用的NumPy轴编号相反。这里的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模块所存取的诸多内容。
netCDF文件操作
导出和导入netCDF文件可以借助xarray,它依赖于pandas,它通过netcdf4-python支持导入导出netCDF-4格式数据,通过SciPy支持其他版本netCDF格式。xarray能够在自身的数据阵列(DataArray)与pandas的序列之间,在自身的数据集(Dataset)与pandas的数据帧之间,进行相互转换:
>> import xarray as xr >> >> df2.to_xarray()
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()
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
这里的日期时间表示遵循了,采用的时间单位为距离某个指定的开始日期时间的日数,历法为前推格里高利历。ncdump的输出所称谓的变量,代表相同类型的值的多维阵列。这里有三个变量:value是数据变量,date和place是坐标变量。变量声明指定了变量的数据类型、名字和以维度名字列表描述的形状,例如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可以按其适合情况转换为五个存储类别(NULL、INTEGER、REAL、TEXT或BLOB)之一,这里的数据帧df2的date纵列中的数据,被转换成为INTEGER、REAL和TEXT三者中的TEXT即文本字符串。
参见
- NumPy
- R语言
- Scikit-learn
*
- 数值分析软件
- matplotlib
- SciPy
- dplyr
引用
延伸阅读
*
*
*
*
外部链接
*
评论 (0)