目录
概述
Series
Series的创建
like-array类型数据创建Series
Dict创建Series
标量创建Series
Series的特点
Series is ndarray-like
Series is dict-like
矢量化操作和标签自动对齐
Name属性
DataFrame
DataFrame的创建
From dict of Series or dicts
From dict of ndarrays / lists
From structured or record array
From a list of dicts
From a dict of tuples
From a Series
DataFrame.from_dict构造函数
DataFrame.from_records构造函数
列标签的选取、增加、删除
方法链中分配新列(Assigning New Columns in Method Chains)
索引/选择(Indexing / Selection)
数据的对齐和算法(Data alignment and arithmetic)
转置(Transposing)
与Numpy函数的互操作性(DataFrame interoperability with NumPy functions)
显示控制(Console display)
IPython在DataFrame列属性访问时的自动补全
(DataFrame column attribute access and IPython completion)
小结
Pandas库的数据结构是依赖于Numpy库的ndarray发展而来的.
Pandas中只有三种类型的数据结构,对比如下:
类型 | 维度(dim) | 形状(shape) | 元素类型 | 说明 |
ndarray(Numpy) | 1或2 | 1×0或者n×m | 同构 | 一维的数组或者多维的矩阵,无索引 |
Series | 1 | m×1 | 非同构 | 带索引的一维数组 |
DataFrame | 2 | m×n | 非同构 | 由多个Series组成的二维表,可以理解为Series容器 |
Panel | 3 | m×n×h | 非同构 | 三维,可以理解为DataFrame容器(将被更高版本的Pandas遗弃 |
鉴于Pandas官方已经声明在以后更高版本的Pandas中,因为使用率低的问题,将抛弃对Pannel的支持,所以本文将不在对Pannel结构进行介绍,仅仅介绍常用的Series和DataFrame. Series和DataFrame数据结构的主要属性:
属性 | 说明 |
index | 返回索引 |
columns | 返回字段名(列名),Series无该属性,但有name属性 |
values | 返回索引元素组成的array |
dtypes | 返回元素类型 |
ndim | 返回维度 |
shape | 返回形状 |
size | 返回所有元素个数 |
itemsize | 返回每个元素所占大小(字节为单位),DataFrame无该属性 |
构造一个用于演示的DataFrame来看看主要的属性:
import pandas as pd
import numpy as np
#制造数据:
np.random.seed(100)
data=np.random.randint(1,10,40).reshape(8,-1)
index=pd.date_range('20180901',periods=8)
col=list('ABCDE')
df=pd.DataFrame(data,index=index,columns=col)
print(df)
#输出:
A B C D E
2018-09-01 7 8 1 1 8
2018-09-02 1 5 6 3 2
2018-09-03 3 6 6 1 5
2018-09-04 5 8 6 3 3
2018-09-05 9 9 7 1 1
2018-09-06 8 1 4 5 8
2018-09-07 8 1 2 1 9
2018-09-08 7 8 4 1 6
查看该对象的属性:
print('index属性: ',df.index)
print('我是分割线'.center(80,'='))
print('columns属性:',df.columns)
print('我是分割线'.center(80,'='))
print('values属性:',df.values)
print('我是分割线'.center(80,'='))
print('dtypes属性:',df.dtypes)
print('我是分割线'.center(80,'='))
print('ndim属性:',df.ndim)
print('我是分割线'.center(80,'='))
print('shape属性:',df.shape)
print('我是分割线'.center(80,'='))
print('size属性:',df.size)
-------------------------------------------------------------------------------------
index属性: DatetimeIndex(['2018-09-01', '2018-09-02', '2018-09-03', '2018-09-04',
'2018-09-05', '2018-09-06', '2018-09-07', '2018-09-08'],
dtype='datetime64[ns]', freq='D')
=====================================我是分割线======================================
columns属性: Index(['A', 'B', 'C', 'D', 'E'], dtype='object')
=====================================我是分割线======================================
values属性: [[9 9 4 8 8]
[1 5 3 6 3]
[3 3 2 1 9]
[5 1 7 3 5]
[2 6 4 5 5]
[4 8 2 2 8]
[8 1 3 4 3]
[6 9 2 1 8]]
=====================================我是分割线======================================
dtypes属性: A int32
B int32
C int32
D int32
E int32
dtype: object
=====================================我是分割线======================================
ndim属性: 2
=====================================我是分割线======================================
shape属性: (8, 5)
=====================================我是分割线======================================
size属性: 40
Series是一维的数据结构,可以理解为继承于的一维的ndarray.
Series同时也是Pandas中的基础性的数据结构,DataFrame的每一列数据都是Series,也就是说Series构成了DataFrame.
Series的创建主要使用pd.Series(data, index)方法
其中data参数可以是数组,字典,列表等等类序列数据,甚至也可以是标量值(比如数字5,字母A)
index参数表示的是Series的索引列表,根据data参数的不同设定不同的index参数.
下面介绍几种主要的Series的创建方式.
如果data参数是like-array(类数组)类型,那么index参数的长度必须与data参数的数组长度一致.
如果不指定index参数的话,那么Pandas将按照[0, ..., len(data) - 1]的原则自动创建index索引
pd.Series(np.random.randint(1,10,4),index=list('abcd'))
Out[4]:
a 7
b 1
c 4
d 4
dtype: int32
pd.Series([1,2,3],index=['A','B','C'])
Out[5]:
A 1
B 2
C 3
dtype: int64
从dict创建Series若不指定index参数则默认为dict的key
若指定index参数,则指定的index序列与dict.keys序列的交集作有value的索引
而在dict.keys需要中匹配不到的index元素的value值为NaN
NaN是Pandas中的一个标准的缺失值代表,表示not a number的意思
#高版本:
pd.Series({'b' : 1, 'a' : 0, 'c' : 2})
Out[7]:
b 1
a 0
c 2
dtype: int64
#低版本:
pd.Series({'b' : 1, 'a' : 0, 'c' : 2})
Out[7]:
a 0
b 1
c 2
dtype: int64
pd.Series({'b' : 1, 'a' : 0, 'c' : 2},index=list('abK'))
Out[8]:
a 0.0
b 1.0
K NaN
dtype: float64
从Dcit数据创建的Series对象的数据排列顺序与使用的Python和Pandas版本相关.
Python版本高于3.6,Pandas版本高于0.23,那么数据排列顺序与dict数据插入的顺序一致
若 Python版本低于3.6,Pandas版本低于0.23,那么数据排列顺序以dict中键值的字符顺序为标准.
如果以标量来创建Series,则必须指定index参数,且Series的value值会自动重复到index参数的长度.
pd.Series(5,index=list('abc'))
Out[9]:
a 5
b 5
c 5
dtype: int64
Series数据结构与Numpy的ndarray数据结构是是非相类似的
可以运用绝大部分的Numpy方法和函数,只是切片是针对索引而不是针对数据.
Series切片不仅可以像ndarray一样,同时还可以使用索引进行切片:
s=pd.Series(np.random.randint(1,10,4),index=list('abcdefgh'))
Out[11]:
a 7
b 6
c 9
d 9
dtype: int32
s[0]
Out[12]: 7
s['a']
Out[13]: 7
s[0:2]
Out[14]:
a 7
b 6
dtype: int32
s['a':'c']
Out[15]:
a 7
b 6
c 9
dtype: int32
s[s>8]
Out[16]:
c 9
d 9
dtype: int32
s[[0,2]]
Out[17]:
a 7
c 9
dtype: int32
s[['a','c']]
Out[18]:
a 7
c 9
dtype: int32
np.mean(s)
Out[19]: 6.0
注意:使用索引切片是包含末端,而使用位置切片时不包含末端.
Series对象同时也是like-dict类型.也可类似dict一样取值,赋值,删除值和判断.
s['a']
Out[20]: 7
s['pp']=100
s
Out[21]:
a 7
b 6
c 9
d 9
pp 100
dtype: int32
del s['pp']
s
Out[22]:
a 7
b 6
c 9
d 9
dtype: int32
'b' in s
Out[23]: True
Series对象也支持字典的get方法
s.get('p',np.NaN)
Out[24]: nan
我们知道在使用Numpy的ndarray数据结构时,因为ndarray支持矢量化,所以对ndarray中的数据进行循环时没必要的
同样在Series中,也支持矢量化.
s+s
Out[25]:
a 16
b 2
c 4
d 14
dtype: int32
s*2
Out[26]:
a 16
b 2
c 4
d 14
dtype: int32
同样,我们知道ndarray进行矢量化操作时必须是同形状的,既shape属性一致.
而由于标签自动对齐功能的存在,Series的矢量化再可以直接计算未进行过标签对齐的Series.
在Series中未找到的索引标签将被标记为NaN,这为数据分析带了极大的自由和灵活性.
s[1:]+s[0:-1]
Out[27]:
a NaN
b 16.0
c 18.0
d NaN
dtype: float64
当然产生的缺失值也是可以处理的,参阅Pandas缺失值的处理.
Series的name属性也是很重要的,该属性可以直接修改,也可以重新命名.
区别是直接修改name属性,则是在原对象上修改,而重新命名默认是返回一个新的对象(可以使用参数inplace设置为修改原对象).
此外,Series对象的name属性在创建DaraFrame时可以转化为列标签名
s.name='example'
s1=s.rename('s1')
s
Out[28]:
a 7
b 6
c 9
d 9
Name: example, dtype: int32
s1
Out[29]:
a 7
b 6
c 9
d 9
Name: s1, dtype: int32
DataFrame是一个二维的标签数据结构,不同的列标签可以是不同类型的数据,可以简单的理解为SQL表格
或者拥有同样索引的多个Series的集合.
同Series类似,DataFrame也可以从多种不同类型数据来创建.
同样对于从字典结构创建DataFrame也遵循一样的版本原则和索引匹配原则
只是对于DataFrame来说,除了索引的匹配,还多出了columns的匹配.
最终构成的DataFrame的索引是Series索引的集合,如果没有指定columns,则默认以字典主键名为列名称.
无法匹配的值同样填充NaN.
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
DataFrame的index和columns值可以被分别的访问:
In [39]: df.index
Out[39]: Index(['a', 'b', 'c', 'd'], dtype='object')
In [40]: df.columns
Out[40]: Index(['one', 'two'], dtype='object')
如果指定index参数,则index的长度必须与ndarray或者list一致.
如果不指定则默认[0, ..., len(ndarray/list) - 1].
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
这种情况与数组的字典处理相同.
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
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的索引将和Series一致,如果没有指定columns,则以Series的name属性作为列标签.
s=pd.Series(np.random.randint(1,10,4),index=list('abcd'),name='number')
df=pd.DataFrame(s)
df
Out[54]:
number
a 6
b 1
c 6
d 4
DataFrame.from_dict 方法接收一个值为类ndarray序列的字典,并返回一个DataFrame.
这个方法与DaraFrame的构造方法类似,只是orient参数的默认值被设置为了'cloumns',而DaraFrame的索引也采用默认值.
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',并指定columns参数.
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
from_records方法接受元组列表或具有结构化dtype的ndarray。它与普通的DataFrame构造函数类似,只是产生的DataFrame索引可能是结构化dtype的特定字段.
In [56]: data
Out[56]:
array([(1, 2., b'Hello'), (2, 3., b'World')],
dtype=[('A', '
可以将DataFrame对象看作一个类dict的对象,列标签(columns)的获取,增加,删除与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
DataFrame列标签(columns)的不仅删除方式与dict一致,同时也支持dict的pop方法.
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
当插入的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
在默认的情况下,新插入的列会被放在最后,但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方法可以在现在存在的DataFrame基础上派生出的新的列:
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
上面的例子上,我们插入的是一个预算计算的值,我们也可以插入一个只有一个参数的函数方法:
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方法返回的也是一个元数据的拷贝值,以保持原数据的不可变.
在3.6版本之后的Python中,assign方法开始支持**kwargs类型的参数.
这允许依赖式的分配,在新的列对象创造出来之前在表达式中引用相同的参数.
In [76]: dfa = pd.DataFrame({"A": [1, 2, 3],
....: "B": [4, 5, 6]})
....:
In [77]: dfa.assign(C=lambda x: x['A'] + x['B'],
....: D=lambda x: x['A'] + x['C'])
....:
Out[77]:
A B C D
0 1 4 5 6
1 2 5 7 9
2 3 6 9 12
依赖式引用需要注意一下python版本的差别.
在3.5及更早的Python版本中,即使表达式引用的值在表达式中已经被更新,但依赖引用时所引用的只能是最初的旧值:
#3.5及更早版本的Python
dependent = pd.DataFrame({"A": [1, 1, 1]})
dependent.assign(A=lambda x: x["A"] + 1,
B=lambda x: x["A"] + 2)
Out[80]:
A B
0 2 3
1 2 3
2 2 3
而在3.6版本之后的python中,表达式引用的值可以同步更新:
#3.6及之后版本的Python
dependent = pd.DataFrame({"A": [1, 1, 1]})
dependent.assign(A=lambda x: x["A"] + 1,
B=lambda x: x["A"] + 2)
Out[81]:
A B
0 2 4
1 2 4
2 2 4
索引的基础原则如下:
操作 | 语法 | 返回结果 |
---|---|---|
列标签选择 | df[col] | Series |
行标签选择 | df.loc[label] | Series |
行位置选择 | df.iloc[loc] | Series |
行的切片 | df[1:5] | DataFrame |
bool向量的行选择 | df[bool_ver] | DataFrame |
单行的数据选择,返回的是列标签为索引的Series.
In [80]: df.loc['b']
Out[80]:
one 2
bar 2
flag False
foo bar
one_trunc 2
Name: b, dtype: object
In [81]: df.iloc[2]
Out[81]:
one 3
bar 3
flag True
foo bar
one_trunc NaN
Name: c, dtype: object
更多的原因数据索引和选择的信息,可以参阅另一篇博文: Pandas数据的索引和选择.
在DataFrame中,数据的自动对齐不仅仅是index属性了,还包含columns属性.
对齐后的DataFrame的index和columns值都将是唯一的.
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
4 1.4145 1.9517 -2.3204 NaN
5 -0.4949 -1.6497 -1.0846 NaN
6 -1.0476 -0.7486 -0.8055 NaN
7 NaN NaN NaN NaN
8 NaN NaN NaN NaN
9 NaN NaN NaN NaN
在DataFrame和Series之间执行操作时,默认是在DataFrame列上对齐Series索引,再在行方向上进行广播.
In [85]: df - df.iloc[0]
Out[85]:
A B C D
0 0.0000 0.0000 0.0000 0.0000
1 -1.3593 -0.2487 -0.4534 -1.7547
2 0.2531 0.8297 0.0100 -1.9912
3 -1.3111 0.0543 -1.7249 -1.6205
4 0.5730 1.5007 -0.6761 1.3673
5 -1.7412 0.7820 -1.2416 -2.0531
6 -1.2408 -0.8696 -0.1533 0.0004
7 -0.7439 0.4110 -0.9296 -0.2824
8 -1.1949 1.3207 0.2382 -1.4826
9 2.2938 1.8562 0.7733 -1.4465
在处理时间序列数据的特殊情况下,DataFrame索引也包含日期,广播将按列进行
In [86]: index = pd.date_range('1/1/2000', periods=8)
In [87]: df = pd.DataFrame(np.random.randn(8, 3), index=index, columns=list('ABC'))
In [88]: df
Out[88]:
A B C
2000-01-01 -1.2268 0.7698 -1.2812
2000-01-02 -0.7277 -0.1213 -0.0979
2000-01-03 0.6958 0.3417 0.9597
2000-01-04 -1.1103 -0.6200 0.1497
2000-01-05 -0.7323 0.6877 0.1764
2000-01-06 0.4033 -0.1550 0.3016
2000-01-07 -2.1799 -1.3698 -0.9542
2000-01-08 1.4627 -1.7432 -0.8266
In [89]: type(df['A'])
Out[89]: pandas.core.series.Series
In [90]: df - df['A']
Out[90]:
2000-01-01 00:00:00 2000-01-02 00:00:00 2000-01-03 00:00:00 \
2000-01-01 NaN NaN NaN
2000-01-02 NaN NaN NaN
2000-01-03 NaN NaN NaN
2000-01-04 NaN NaN NaN
2000-01-05 NaN NaN NaN
2000-01-06 NaN NaN NaN
2000-01-07 NaN NaN NaN
2000-01-08 NaN NaN NaN
2000-01-04 00:00:00 ... 2000-01-08 00:00:00 A B C
2000-01-01 NaN ... NaN NaN NaN NaN
2000-01-02 NaN ... NaN NaN NaN NaN
2000-01-03 NaN ... NaN NaN NaN NaN
2000-01-04 NaN ... NaN NaN NaN NaN
2000-01-05 NaN ... NaN NaN NaN NaN
2000-01-06 NaN ... NaN NaN NaN NaN
2000-01-07 NaN ... NaN NaN NaN NaN
2000-01-08 NaN ... NaN NaN NaN NaN
[8 rows x 11 columns]
警告:
该之前的版本中,一下的减法形式将被弃用:
df - df['A']
而应该采用新的方式:
df.sub(df['A'], axis=0)
与标量的操作仍然会自动的广播:
In [91]: df * 5 + 2
Out[91]:
A B C
2000-01-01 -4.1341 5.8490 -4.4062
2000-01-02 -1.6385 1.3935 1.5106
2000-01-03 5.4789 3.7087 6.7986
2000-01-04 -3.5517 -1.0999 2.7487
2000-01-05 -1.6617 5.4387 2.8822
2000-01-06 4.0165 1.2252 3.5081
2000-01-07 -8.8993 -4.8492 -2.7710
2000-01-08 9.3135 -6.7158 -2.1330
bool值的操作也同样支持:
符号 | 含义 |
---|---|
& | 类似逻辑运算and |
| | 类似逻辑运算or |
^ | 一真一假为True,其余为False |
- | 取反 |
In [94]: df1 = pd.DataFrame({'a' : [1, 0, 1], 'b' : [0, 1, 1] }, dtype=bool)
In [95]: df2 = pd.DataFrame({'a' : [0, 1, 1], 'b' : [1, 1, 0] }, dtype=bool)
In [96]: df1 & df2
Out[96]:
a b
0 False False
1 False True
2 True False
In [97]: df1 | df2
Out[97]:
a b
0 True True
1 True True
2 True True
In [98]: df1 ^ df2
Out[98]:
a b
0 True True
1 True False
2 False True
In [99]: -df1
Out[99]:
a b
0 False True
1 True False
2 False False
与ndarray类似,使用.T属性可以将DataFrame转置.
# only show the first 5 rows
In [100]: df[:5].T
Out[100]:
2000-01-01 2000-01-02 2000-01-03 2000-01-04 2000-01-05
A -1.2268 -0.7277 0.6958 -1.1103 -0.7323
B 0.7698 -0.1213 0.3417 -0.6200 0.6877
C -1.2812 -0.0979 0.9597 0.1497 0.1764
Numpy的元素级的一元函数和其他函数都可以在DataFrame上使用
In [101]: np.exp(df)
Out[101]:
A B C
2000-01-01 0.2932 2.1593 0.2777
2000-01-02 0.4830 0.8858 0.9068
2000-01-03 2.0053 1.4074 2.6110
2000-01-04 0.3294 0.5380 1.1615
2000-01-05 0.4808 1.9892 1.1930
2000-01-06 1.4968 0.8565 1.3521
2000-01-07 0.1131 0.2541 0.3851
2000-01-08 4.3176 0.1750 0.4375
In [102]: np.asarray(df)
Out[102]:
array([[-1.2268, 0.7698, -1.2812],
[-0.7277, -0.1213, -0.0979],
[ 0.6958, 0.3417, 0.9597],
[-1.1103, -0.62 , 0.1497],
[-0.7323, 0.6877, 0.1764],
[ 0.4033, -0.155 , 0.3016],
[-2.1799, -1.3698, -0.9542],
[ 1.4627, -1.7432, -0.8266]])
.dot方法提供了矩阵的乘法运算:
In [103]: df.T.dot(df)
Out[103]:
A B C
A 11.3419 -0.0598 3.0080
B -0.0598 6.5206 2.0833
C 3.0080 2.0833 4.3105
类似的,在Series上.dot方法可以实现乘法:
In [104]: s1 = pd.Series(np.arange(5,10))
In [105]: s1.dot(s1)
Out[105]: 255
需要注意的是,DataFrame并不是ndarray的完全替代,因为DataFrame的索引语义在某些地方与矩阵还是存在不同的。
超大的数据在控制台显示是将被截取,可以使用info()方法获取信息摘要.
这里以R语言中的棒球集数据为例:
In [106]: baseball = pd.read_csv('data/baseball.csv')
In [107]: print(baseball)
id player year stint ... hbp sh sf gidp
0 88641 womacto01 2006 2 ... 0.0 3.0 0.0 0.0
1 88643 schilcu01 2006 1 ... 0.0 0.0 0.0 0.0
.. ... ... ... ... ... ... ... ... ...
98 89533 aloumo01 2007 1 ... 2.0 0.0 3.0 13.0
99 89534 alomasa02 2007 1 ... 0.0 0.0 0.0 0.0
[100 rows x 23 columns]
In [108]: baseball.info()
RangeIndex: 100 entries, 0 to 99
Data columns (total 23 columns):
id 100 non-null int64
player 100 non-null object
year 100 non-null int64
stint 100 non-null int64
team 100 non-null object
lg 100 non-null object
g 100 non-null int64
ab 100 non-null int64
r 100 non-null int64
h 100 non-null int64
X2b 100 non-null int64
X3b 100 non-null int64
hr 100 non-null int64
rbi 100 non-null float64
sb 100 non-null float64
cs 100 non-null float64
bb 100 non-null int64
so 100 non-null float64
ibb 100 non-null float64
hbp 100 non-null float64
sh 100 non-null float64
sf 100 non-null float64
gidp 100 non-null float64
dtypes: float64(9), int64(11), object(3)
memory usage: 18.0+ KB
使用to_string将以表格形式返回DataFrame的字符串表示:
df= pd.DataFrame({'a' : [0, 1, 1], 'b' : [0, 1, 0] }, dtype=bool)
type(df.to_string())
Out[200]:
df.to_string()
Out[201]:
a b
0 False False
1 True True
2 True False
在默认情况下,宽数据框将跨多行打印,但可以通过display.width属性来设置单行的打印宽度.
In [111]: pd.set_option('display.width', 40) # default is 80
In [112]: pd.DataFrame(np.random.randn(3, 12))
Out[112]:
0 1 2 3 4 5 6 7 8 9 10 11
0 1.262731 1.289997 0.082423 -0.055758 0.536580 -0.489682 0.369374 -0.034571 -2.484478 -0.281461 0.030711 0.109121
1 1.126203 -0.977349 1.474071 -0.064034 -1.282782 0.781836 -1.071357 0.441153 2.353925 0.583787 0.221471 -0.744471
2 0.758527 1.729689 -0.964980 -0.845696 -1.340896 1.846883 -1.328865 1.682706 -1.717693 0.888782 0.228440 0.901805
甚至可以通过设置display.max_colwidth来调整各个列的最大宽度
In [113]: datafile={'filename': ['filename_01','filename_02'],
.....: 'path': ["media/user_name/storage/folder_01/filename_01",
.....: "media/user_name/storage/folder_02/filename_02"]}
.....:
In [114]: pd.set_option('display.max_colwidth',30)
In [115]: pd.DataFrame(datafile)
Out[115]:
filename path
0 filename_01 media/user_name/storage/fo...
1 filename_02 media/user_name/storage/fo...
In [116]: pd.set_option('display.max_colwidth',100)
In [117]: pd.DataFrame(datafile)
Out[117]:
filename path
0 filename_01 media/user_name/storage/folder_01/filename_01
1 filename_02 media/user_name/storage/folder_02/filename_02
当然还可以通过expand_frame_repr选项禁用此特性,这将把表打印在一个块中.
如果DataFrame列标签是一个有效的Python变量名,那么可以像访问属性一样访问该列:
In [118]: df = pd.DataFrame({'foo1' : np.random.randn(5),
.....: 'foo2' : np.random.randn(5)})
.....:
In [119]: df
Out[119]:
foo1 foo2
0 1.171216 -0.858447
1 0.520260 0.306996
2 -1.197071 -0.028665
3 -1.066969 0.384316
4 -0.303421 1.574159
In [120]: df.foo1
Out[120]:
0 1.171216
1 0.520260
2 -1.197071
3 -1.066969
4 -0.303421
Name: foo1, dtype: float64
在Ipython中
In [5]: df.fo
df.foo1 df.foo2
本章主要介绍了Pandas中的最重要的两个数据结构类型,Series和DataFrame.
理解以下最要的两点非常重要:
1.数据的自动对齐
2.原数据对象的不可变更性,大多数的方法返回的都是一个新的对象,而不是在原数据上进行操作.