Pandas是一个Python包,提供快速、灵活和富有表现力的数据结构,使关联或标记数据的使用既简单又直观。
它旨在成为Python中进行实际,真实世界数据分析的基础高级构建块。此次外还有更广泛的目标,即称为任何语言中最强大,最灵活的开源数据分析/操作工具。
适合许多不同类型的数据
- 具有异构类型列的表格数据,如SQL表或Excel表
- 有序和无序的时间序列数据
- 具有行和列标签的任意矩阵数据
- 任何其他形式的观察/统计数据集。实际上不需要将数据标记为放置在pandas数据结构中
主要数据结构是Series(一维)和DataFrame(二维)处理金融,统计,社会科学和许多工程领域中的绝大多数典型用例。Pandas建立在NumPy之上,与许多其他第三方库完美集成。
数据结构
数据对齐是固有的
- import numpy as np
- import pandas as pd
- import matplotlib.pyplot as plt
Series是一维标记的数组,能够保存任何数据类型。轴标签统称为索引,创建系列的基本方法是调用
- s = pd.Series(data,index=index)
data可以有很多不同的东西,比如
- 一个Python字典
- 一个ndarray
- 标量
传递的索引是轴标签列表。因此根据数据的不同,可以分为几种情况
来自ndarray
如果data是ndarray,则索引的长度必须与数据的长度相同。如果没有传递索引,将创建一个具有值的索引
pd.Series(np.random.rand(5))
来自dict
可以从dicts实例化
pd.Series({'b':1})
来自标量值
如果data是标量值,则必须提供索引。将重复该值以匹配索引的长度
pd.Series(5.,index=['a','b'])
index是行索引,columns是列索引
可以对Series进行计算和切片等操作
系列也可以有一个name属性
s = pd.Series(np.random.randn(5),name='something')
DataFrame是一个二维标记数据结构,具有可能不同类型的列。可以将其视为电子表格或SQL表,或Series对象的字段。通常是最常用的pandas对象。接受不同类型的输入
- 1D ndarray,list,dicts或Series的Dict
- 二维numpy.ndarray
- 结构化或记录ndarray
- 一个Series
- 另一个DataFrame
除了数据,还可以传递索引(行标签)和列(列标签)参数。如果传递索引和/或列,则可以保证生成的DataFrame的索引和/或列。
来自dict或Series的dicts
得到的指数将是各种系列的指标。如果有任何嵌套的dicts,将首先转换为Series。
In [34]: d = {'one' : pd.Series([1., 2., 3.], index=['a', 'b', 'c']), ....: 'two' : pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])} ....: In [35]: df = pd.DataFrame(d) In [36]: df Out[36]: one two a 1.0 1.0 b 2.0 2.0 c 3.0 3.0 d NaN 4.0 In [37]: pd.DataFrame(d, index=['d', 'b', 'a']) Out[37]: one two d NaN 4.0 b 2.0 2.0 a 1.0 1.0 In [38]: pd.DataFrame(d, index=['d', 'b', 'a'], columns=['two', 'three']) Out[38]: two three d 4.0 NaN b 2.0 NaN a 1.0 NaN
通过访问索引和列数据,可以分别访问行和列标签
In [39]: df.index Out[39]: Index(['a', 'b', 'c', 'd'], dtype='object') In [40]: df.columns Out[40]: Index(['one', 'two'], dtype='object')
来自ndarrays 、lists的字典
ndarrays必须都是相同的长度。如果传递索引,则它必须明显与数组的长度相同。如果没有传递索引,结果将是range(n)
In [41]: d = {'one' : [1., 2., 3., 4.], ....: 'two' : [4., 3., 2., 1.]} ....: In [42]: pd.DataFrame(d) Out[42]: one two 0 1.0 4.0 1 2.0 3.0 2 3.0 2.0 3 4.0 1.0 In [43]: pd.DataFrame(d, index=['a', 'b', 'c', 'd']) Out[43]: one two a 1.0 4.0 b 2.0 3.0 c 3.0 2.0 d 4.0 1.0
来自structrued或record array
处理方式与数组的字段相同
In [44]: data = np.zeros((2,), dtype=[('A', 'i4'),('B', 'f4'),('C', 'a10')]) In [45]: data[:] = [(1,2.,'Hello'), (2,3.,"World")] In [46]: pd.DataFrame(data) Out[46]: A B C 0 1 2.0 b'Hello' 1 2 3.0 b'World' In [47]: pd.DataFrame(data, index=['first', 'second']) Out[47]: A B C first 1 2.0 b'Hello' second 2 3.0 b'World' In [48]: pd.DataFrame(data, columns=['C', 'A', 'B']) Out[48]: C A B 0 b'Hello' 1 2.0 1 b'World' 2 3.0
来自dicts列表
In [49]: data2 = [{'a': 1, 'b': 2}, {'a': 5, 'b': 10, 'c': 20}] In [50]: pd.DataFrame(data2) Out[50]: a b c 0 1 2 NaN 1 5 10 20.0 In [51]: pd.DataFrame(data2, index=['first', 'second']) Out[51]: a b c first 1 2 NaN second 5 10 20.0 In [52]: pd.DataFrame(data2, columns=['a', 'b']) Out[52]: a b 0 1 2 1 5 10
来自元组
In [53]: pd.DataFrame({('a', 'b'): {('A', 'B'): 1, ('A', 'C'): 2}, ....: ('a', 'a'): {('A', 'C'): 3, ('A', 'B'): 4}, ....: ('a', 'c'): {('A', 'B'): 5, ('A', 'C'): 6}, ....: ('b', 'a'): {('A', 'C'): 7, ('A', 'B'): 8}, ....: ('b', 'b'): {('A', 'D'): 9, ('A', 'B'): 10}}) ....: Out[53]: a b b a c a b A B 1.0 4.0 5.0 8.0 10.0 C 2.0 3.0 6.0 7.0 NaN D NaN NaN NaN NaN 9.0
构造函数
DataFrame.from_dict采用dicts的dict或类似数组序列的dict并返回DataFrame。DataFrame除了默认情况下的orient参数外,它的操作类似于构造函数columns,但可以将其设置index为使用dict键作为行标签
In [54]: pd.DataFrame.from_dict(dict([('A', [1, 2, 3]), ('B', [4, 5, 6])])) Out[54]: A B 0 1 4 1 2 5 2 3 6
如果设置orient='index',则键将是行标签。还可以传递所需的列名称
In [55]: pd.DataFrame.from_dict(dict([('A', [1, 2, 3]), ('B', [4, 5, 6])]), ....: orient='index', columns=['one', 'two', 'three']) ....: Out[55]: one two three A 1 2 3 B 4 5 6
DataFrame.from_record获取元组列表或带有结构化dtype的ndarray。类似于普通DataFrame构造函数,但生产的DataFrame索引可能是结构化dtype的特定字段
In [57]: pd.DataFrame.from_records(data, index='C') Out[57]: A B C b'Hello' 1 2.0 b'World' 2 3.0
列选择、添加、删除
可以将DataFrame视为类似索引的Series对象的dict。获取,设置和删除的工作方式与dict操作相同
In [58]: df['one'] Out[58]: a 1.0 b 2.0 c 3.0 d NaN Name: one, dtype: float64 In [59]: df['three'] = df['one'] * df['two'] In [60]: df['flag'] = df['one'] > 2 In [61]: df Out[61]: one two three flag a 1.0 1.0 1.0 False b 2.0 2.0 4.0 False c 3.0 3.0 9.0 True d NaN 4.0 NaN False
删除
In [62]: del df['two'] In [63]: three = df.pop('three') In [64]: df Out[64]: one flag a 1.0 False b 2.0 False c 3.0 True d NaN False
插入
In [65]: df['foo'] = 'bar' In [66]: df Out[66]: one flag foo a 1.0 False bar b 2.0 False bar c 3.0 True bar d NaN False bar
如果插入与DataFrame不具有相同索引的Series时,将符合DataFrame的索引
In [67]: df['one_trunc'] = df['one'][:2] In [68]: df Out[68]: one flag foo one_trunc a 1.0 False bar 1.0 b 2.0 False bar 2.0 c 3.0 True bar NaN d NaN False bar NaN
可以插入原始的ndarrays,但他们的长度必须与DataFrame索引的长度相匹配
默认情况下,列会在末尾插入。该insert函数可以用于插入列的特定位置
In [69]: df.insert(1, 'bar', df['one']) In [70]: df Out[70]: one bar flag foo one_trunc a 1.0 1.0 False bar 1.0 b 2.0 2.0 False bar 2.0 c 3.0 3.0 True bar NaN d NaN NaN False bar NaN
在方法链中分配新列
DataFrame有一种assign()方法可以创建从现有列派生的新列
In [71]: iris = pd.read_csv('data/iris.data') In [72]: iris.head() Out[72]: SepalLength SepalWidth PetalLength PetalWidth Name 0 5.1 3.5 1.4 0.2 Iris-setosa 1 4.9 3.0 1.4 0.2 Iris-setosa 2 4.7 3.2 1.3 0.2 Iris-setosa 3 4.6 3.1 1.5 0.2 Iris-setosa 4 5.0 3.6 1.4 0.2 Iris-setosa In [73]: (iris.assign(sepal_ratio = iris['SepalWidth'] / iris['SepalLength']) ....: .head()) ....: Out[73]: SepalLength SepalWidth PetalLength PetalWidth Name sepal_ratio 0 5.1 3.5 1.4 0.2 Iris-setosa 0.6863 1 4.9 3.0 1.4 0.2 Iris-setosa 0.6122 2 4.7 3.2 1.3 0.2 Iris-setosa 0.6809 3 4.6 3.1 1.5 0.2 Iris-setosa 0.6739 4 5.0 3.6 1.4 0.2 Iris-setosa 0.7200
我们插入了一个预先计算的值,还可以传入一个参数的函数,以便在分配给DataFrame上进行求值
In [74]: iris.assign(sepal_ratio = lambda x: (x['SepalWidth'] / ....: x['SepalLength'])).head() ....: Out[74]: SepalLength SepalWidth PetalLength PetalWidth Name sepal_ratio 0 5.1 3.5 1.4 0.2 Iris-setosa 0.6863 1 4.9 3.0 1.4 0.2 Iris-setosa 0.6122 2 4.7 3.2 1.3 0.2 Iris-setosa 0.6809 3 4.6 3.1 1.5 0.2 Iris-setosa 0.6739 4 5.0 3.6 1.4 0.2 Iris-setosa 0.7200
assign始终返回数据的副本,保持原始DataFrame不变
当没有引用DataFrame时,传递可调用的,而不是要插入的实际值。这assign在操作链中使用时很常见
In [75]: (iris.query('SepalLength > 5') ....: .assign(SepalRatio = lambda x: x.SepalWidth / x.SepalLength, ....: PetalRatio = lambda x: x.PetalWidth / x.PetalLength) ....: .plot(kind='scatter', x='SepalRatio', y='PetalRatio'))
索引选择
选择列:df[col]:系列
按标签选择行:df.loc[label]:系列
按整数位置选择行:df.iloc[loc]:系列
切片行:df[5:10]:数据帧
按布尔向量选择行:df[bool_vec]:数据帧
数据对齐和算术
DataFrame对象之间的数据对其自动在列和索引(行标签)上对齐。同样生成的对象具有列和行标签的并集
In [82]: df = pd.DataFrame(np.random.randn(10, 4), columns=['A', 'B', 'C', 'D']) In [83]: df2 = pd.DataFrame(np.random.randn(7, 3), columns=['A', 'B', 'C']) In [84]: df + df2 Out[84]: A B C D 0 0.0457 -0.0141 1.3809 NaN 1 -0.9554 -1.5010 0.0372 NaN 2 -0.6627 1.5348 -0.8597 NaN 3 -2.4529 1.2373 -0.1337 NaN
DataFrame和Series之间执行操作时,默认行为是在DataFrame列上对齐Series索引,从而按行进行广播
df - df.iloc[0]
在使用时间序列数据的特殊情况下,DataFrame索引还包含日期,广播将按列进行
index = pd.date_range('1/1/2000', periods=8)
df = pd.DataFrame(np.random.randn(8, 3), index=index, columns=list('ABC'))
df*5+2
1/df
df ** 4
df1 & df2
df1 | df2
df1 ^ df2
-df1
转置
要进行转置,需要访问T属性,类似于ndarray
df[:5].T
DataFrame与NumPy函数的互操作性
可以在DataFrame上使用其他的Numpy函数
np.exp(df)
np.asarray(df)
df.T.dot(df)
DataFrame列属性访问
如果DataFrame列标签是有效的Python变量名称,则可以像属性一样访问
df.A
基本功能
要查看Series或DataFrame对象的小样本,请使用head()和tail()方法。显示的默认元素数为5,但您可以传递自定义数字。
long_series = pd.Series(np.random.randn(100))
long_series.head() //查看头
long_series.tail(3) //查看末尾
属性和原始ndarray(s)
df.columns = [x.lower() for x in df.columns] //列名小写
df.values 访问实际数据
加速操作
pandas支持使用numexpr库和bottleneck库加速某些类型的二进制数值和布尔运算
pd.set_option('compute.use_bottleneck', False) pd.set_option('compute.use_numexpr', False)
匹配和广播
数据框所拥有的方法add(),sub(),mul(),div()和相关的功能radd(),rsub()用于执行二进制运算。
对于广播行为,系列输入是主要关注点。可以通过axis关键字匹配索引或列。
填充值数据的操作
算术函数可以选择输入fill_value,即当缺少某个位置时需要替换的值。
df.add(df2,fill_value=0)
布尔缩减
可以使用empty,any(),all,bool()提供一种方法来概括一个布尔结果
- (df>0).all()
- (df>0).any()
- df.empty
比较对象是否相等
df+df != df*2 这个表达式是错误的
(df+df).equals(df*2) 应该使用这个表达式
比较类似数组的对象
pandas数据结构与标量值进行比较时,可以用下面方式执行元素比较
In [64]: pd.Series(['foo', 'bar', 'baz']) == 'foo' Out[64]: 0 True 1 False 2 False dtype: bool In [65]: pd.Index(['foo', 'bar', 'baz']) == 'foo' Out[65]: array([ True, False, False], dtype=bool)
pandas还处理相同长度的不同数组对象之间的元素比较
In [66]: pd.Series(['foo', 'bar', 'baz']) == pd.Index(['foo', 'bar', 'qux']) Out[66]: 0 True 1 True 2 False dtype: bool In [67]: pd.Series(['foo', 'bar', 'baz']) == np.array(['foo', 'bar', 'qux']) Out[67]: 0 True 1 True 2 False dtype: bool
尝试比较Index或Series不同长度的对象将引发ValueError
注意:这个和NumPy的广播不一样
组合重叠数据集
两个相似数据集的组合,其中一个比较好。我们希望组合两个DataFrame对象,其中一个DataFrame中的缺失值有条件地填充来自其他DataFrame的类似标记的值。实现操作的函数是combine_first(),如同位置两边都存在则使用第一个。
In [70]: df1 = pd.DataFrame({'A' : [1., np.nan, 3., 5., np.nan], ....: 'B' : [np.nan, 2., 3., np.nan, 6.]}) ....: In [71]: df2 = pd.DataFrame({'A' : [5., 2., 4., np.nan, 3., 7.], ....: 'B' : [np.nan, np.nan, 3., 4., 6., 8.]}) ....: In [72]: df1 Out[72]: A B 0 1.0 NaN 1 NaN 2.0 2 3.0 3.0 3 5.0 NaN 4 NaN 6.0 In [73]: df2 Out[73]: A B 0 5.0 NaN 1 2.0 NaN 2 4.0 3.0 3 NaN 4.0 4 3.0 6.0 5 7.0 8.0 In [74]: df1.combine_first(df2) Out[74]: A B 0 1.0 NaN 1 2.0 2.0 2 3.0 3.0 3 5.0 4.0 4 3.0 6.0 5 7.0 8.0
通用DataFrame组合
另一个DataFrame和组合器函数,对齐输入DataFrame,然后传递Series的组合器函数对(名称相同的列)
In [75]: combiner = lambda x, y: np.where(pd.isna(x), y, x) In [76]: df1.combine(df2, combiner)
描述性统计
http://pandas.pydata.org/pandas-docs/stable/basics.html