阅读笔记:利用Python进行数据分析第2版——第5章 pandas入门

pandas经常和其它工具一同使用,如数值计算工具NumPy和SciPy,分析库statsmodels和scikit-learn,和数据可视化库matplotlib。pandas是基于NumPy数组构建的,特别是基于数组的函数和不使用for循环的数据处理。

Series

  1. Series是一种类似于一维数组的对象,它由一组数据(各种NumPy数据类型) 以及一组与之相关的数据标签(即索引)组成。
import pandas as pd
from pandas import Series, DataFrame
obj = pd.Series([4, 7, -5, 3])
  1. 使用NumPy函数或类似NumPy的运算(如根据布尔型数组进行过滤、标量乘法、应用数学函数等)都会保留索引值的链接
  2. 使用NumPy函数或类似NumPy的运算(如根据布尔型数组进行过滤、标量乘法、应用数学函数等)都会保留索引值的链接。如果数据被存放在一个Python字典中,也可以直接通过这个字典来创建Series
'b' in obj
sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}
obj3 = pd.Series(sdata)
  1. 对于许多应用而言,Series最重要的一个功能是,它会根据运算的索引标签自动对齐数据。
  2. Series对象本身及其索引都有一个name属性:
In [30]: obj4.name = 'population'
In [31]: obj4.index.name = 'state'
In [32]: obj4
Out[32]:
state
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
Name: Population, dtype: float64\
  1. Series的索引可以通过赋值的方式就地修改:obj.index = ['Bob', 'Steve', 'Jeff', 'Ryan']

DataFrame

DataFrame是一个表格型的数据结构,它含有一组有序的列, 每列可以是不同的值类型( 数值、字符串、布尔值等)。DataFrame既有行索引也有列索引, 它可以被看做由Series组成的字典(共用同一个索引)。DataFrame中的数据是以一个或多个二维块存放的(而不是列表、字典或别的一维数据结构)。

  1. DataFrame会自动加上索引( 跟Series一样),且全部列会被有序排列。如果指定了列序列,则DataFrame的列就会按照指定顺序进行排列:
data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'], 'year': [2000, 2001, 2002, 2001, 2002, 2003], 'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
frame = pd.DataFrame(data)
  1. 通过类似字典标记的方式或属性的方式,可以将DataFrame的列获取为一个Series:
    注意:frame[column]适用于任何列的名, 但是frame.column只有在列名是一个合理的Python变量名时才适用。
In [51]: frame['state']
Out[51]: 
0      Ohio
1      Ohio
2      Ohio
3    Nevada
4    Nevada
5    Nevada
Name: state, dtype: object
  1. 行也可以通过位置或名称的方式进行获取, 比如用loc属性:
frame2 = pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'], index=['one', 'two', 'three', 'four', 'five', 'six'])
frame.loc[1]
frame2.loc['three']
  1. 列可以通过赋值的方式进行修改。例如,我们可以给那个空的”debt”列赋上一个标量值或一组值:frame2['debt'] = 16.5frame2['debt'] = np.arange(6.)
  2. 注意:将列表或数组赋值给某个列时, 其长度必须跟DataFrame的长度相匹配。 如果赋值的是一个Series,就会精确匹配DataFrame的索引, 所有的空位都将被填上缺失值。
  3. 为不存在的列赋值会创建出一个新列。关键字del用于删除列
  4. 注意: 通过索引方式返回的列只是相应数据的视图而已,并不是副本。因此,对返回的Series所做的任何就地修改全都会反映到源DataFrame上。通过Seriescopy方法即可指定复制列。
  5. 如果嵌套字典传给DataFramepandas就会被解释为:外层字典的键作为列,内层键则作为行索引:
pop = {'Nevada': {2001: 2.4, 2002: 2.9}, 'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}
frame3 = pd.DataFrame(pop)
Nevada	Ohio
2000	NaN	1.5
2001	2.4	1.7
2002	2.9	3.6
frame3.T  # 转置
  1. 内层字典的键会被合并、排序以形成最终的索引。如果明确指定了索引,则不会这样。表5-1列出了DataFrame构造函数所能接受的各种数据:
    可以输入给DataFrame构造器的数据
  2. pandas的索引对象负责管理轴标签和其他元数据( 比如轴名称等) 。构建SeriesDataFrame时,所用到的任何数组或其他序列的标签都会被转换成一个IndexIndex对象是不可变的, 因此用户不能对其进行修改。labels = pd.Index(np.arange(3))
  3. 除了类似于数组,Index的功能也类似一个固定大小的集合,但与python的集合不同,pandasIndex可以包含重复的标签:dup_labels = pd.Index(['foo', 'foo', 'bar', 'bar']),选择重复的标签,会显示所有的结果。 index的方法和属性
  4. reindex作用是创建一个新对象,它的数据符合新的索引。用该Series的reindex将会根据新索引进行重排。如果某个索引值当前不存在,就引入缺失值
obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])
obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])
obj.index = ['a', 'b', 'c', 'd', 'e']  # 会报错
obj.index = ['a', 'b', 'c', 'd']  # 会改变数据对应关系
  1. 对于时间序列这样的有序数据,重新索引时可能需要做一些插值处理。 method选项即可达到此目的,例如,使用ffill可以实现前向值填充:
obj3 = pd.Series(['blue', 'purple', 'yellow'], index=[0, 2, 4])
obj3.reindex(range(6), method='ffill')
  1. 借助DataFramereindex可以修改( 行)索引和列。只传递一个序列时,会重新索引结果的行,列可以用columns关键字重新索引:
frame = pd.DataFrame(np.arange(9).reshape((3, 3)), index=['a', 'c', 'd'],columns=['Ohio', 'Texas', 'California'])
frame2 = frame.reindex(['a', 'b', 'c', 'd'])
states = ['Texas', 'Utah', 'California']
frame.reindex(columns=states)

reindex函数的参数
15. 丢弃某条轴上的一个或多个项很简单,只要有一个索引数组或列表即可。由于需要执行一些数据整理和集合逻辑,所以drop方法返回的是一个在指定轴上删除了指定值的新对象del是直接原地删除:

obj = pd.Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e'])
obj1 = obj.drop('c')  # obj对象不变
obj2 = obj.drop(['c', 'd'])  # obj对象不变
del obj['c']  # obj对象发生变化
  1. 对于DataFrame,可以删除任意轴上的索引值。 用标签序列调用drop会从行标签( axis 0) 删除值,通过传递axis=1axis='columns'可以删除列的值:
data = pd.DataFrame(np.arange(16).reshape((4, 4)), index=['Ohio', 'Colorado', 'Utah', 'New York'], columns=['one', 'two', 'three', 'four'])
data.drop(['Colorado', 'Ohio'])
data.drop('one')  # 报错
data.drop('one', axis=1)
data.drop(['two', 'four'], axis='columns')
data.drop(['Colorado', 'Ohio'], inplace=True)  # 就地修改数据,小心使用
  1. Series索引的工作方式类似于NumPy数组的索引, 只不过Series的索引值不只是整数。
    注意:利用标签的切片运算与普通的Python切片运算不同,其末端是包含的
obj = pd.Series(np.arange(4.), index=['a', 'b', 'c', 'd'])
obj['b']  # 1.0
obj[1]  # 1.0
obj[2:4]  # 2.0 3.0
obj[['b', 'a', 'd']]
obj[[1, 3]]
obj['b':'c']  # 1.0 2.0

用切片可以对Series的相应部分进行设置:obj['b':'c'] = 5
18. 需要注意的是,data['one']可以直接获取列数据,但data.drop['one']不被允许,data.drop('Utah')可以直接删除行数据,但data['Utah']不被允许,会报错。且data[1:2]可以获取第二行数据,但data[1]不被允许,会报错。

data = pd.DataFrame(np.arange(16).reshape((4, 4)), index=['Ohio', 'Colorado', 'Utah', 'New York'], columns=['one', 'two', 'three', 'four'])
data['two']  # 获取第二列
data[['three', 'one']]
data[:2]  # 获取前两行
data[data['three'] > 5]
  1. 另一种用法是通过布尔型DataFrame(比如下面这个由标量比较运算得出的)进行索引:
In [134]: data < 5
Out[134]: one	 two	three	four
Ohio	  True	 True	True	True
Colorado  True	 False	False	False
Utah	  False	 False	False	False
New York  False	 False	False	False
In [135]: data[data < 5] = 0
  1. 用loc和iloc进行选取:
In [137]: data.loc['Colorado', ['two', 'three']]  # 通过标签选取
In [138]: data.iloc[2, [3, 0, 1]]  # 通过下标整数进行选取
In [140]: data.iloc[[1, 2], [3, 0, 1]]
In [141]: data.loc[:'Utah', 'two']
In [142]: data.iloc[:, :3][data.three > 5]

DataFrame选取数据方法

  1. 尽量避免直接使用整数索引obj[1]obj[-1](会报错),为了避免错误,请使用iloc和loc。
  2. 算术运算和数据对齐:pandas最重要的一个功能是,它可以对不同索引的对象进行算术运算。在将对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的并集。
s1 = pd.Series([7.3, -2.5, 3.4, 1.5], index=['a', 'c', 'd', 'e'])
s2 = pd.Series([-2.1, 3.6, -1.5, 4, 3.1], index=['a', 'c', 'e', 'f', 'g'])
s1 + s2
a    5.2
c    1.1
d    NaN
e    0.0
f    NaN
g    NaN
dtype: float64

自动的数据对齐操作在不重叠的索引处引入了NA值。缺失值会在算术运算过程中传播。
对于DataFrame,对齐操作会同时发生在行和列上

In [168]: s1 + s2
Out[168]:
a    5.2
c    1.1
d    NaN
e    0.0
f    NaN
g    NaN
dtype: float64
In [169]: s1.add(s2, fill_value=1)  # 对s1和s2中的nan值用1进行填充然后进行计算
Out[169]:
a    5.2
c    1.1
d    4.4
e    0.0
f    5.0
g    4.1
dtype: float64

Series和DataFrame的算术方法

  1. 默认情况下,DataFrame和Series之间的算术运算会将Series的索引匹配到DataFrame的列,然后沿着行一直向下广播
In [179]: frame = pd.DataFrame(np.arange(12.).reshape((4, 3)),
   .....:                      columns=list('bde'),
   .....:                      index=['Utah', 'Ohio', 'Texas', 'Oregon'])
In [180]: series = frame.iloc[0]
In [181]: frame
Out[181]: 
          b     d     e
Utah    0.0   1.0   2.0
Ohio    3.0   4.0   5.0
Texas   6.0   7.0   8.0
Oregon  9.0  10.0  11.0
In [182]: series
Out[182]: 
b    0.0
d    1.0
e    2.0
Name: Utah, dtype: float64
In [183]: frame - series
Out[183]: 
          b    d    e
Utah    0.0  0.0  0.0
Ohio    3.0  3.0  3.0
Texas   6.0  6.0  6.0
Oregon  9.0  9.0  9.0

如果你希望匹配行且在列上广播,则必须使用算术运算方法。例如:

In [188]: series3 = frame['d']
In [189]: frame.sub(series3, axis='index')
Out[189]: 
          b    d    e
Utah   -1.0  0.0  1.0
Ohio   -1.0  0.0  1.0
Texas  -1.0  0.0  1.0
Oregon -1.0  0.0  1.0
# 等价于
In [190]: frame.sub(series3, axis=0)
  1. NumPy的ufuncs(元素级数组方法)也可用于操作pandas对象:
frame = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon'])
np.abs(frame)
f = lambda x: x.max() - x.min()
frame.apply(f)
  1. 传递到apply的函数不是必须返回一个标量,还可以返回由多个值组成的Series
In [196]: def f(x):
   .....:     return pd.Series([x.min(), x.max()], index=['min', 'max'])
In [197]: frame.apply(f)
Out[197]: 
            b         d         e
min -0.555730  0.281746 -1.296221
max  1.246435  1.965781  1.393406

元素级的Python函数也是可以用的。假如你想得到frame中各个浮点值的格式化字符串,使用applymap即可。之所以叫做applymap,是因为Series有一个用于应用元素级函数的map方法:

In [198]: format = lambda x: '%.2f' % x
In [199]: frame.applymap(format)
Out[199]: 
            b     d      e
Utah    -0.20  0.48  -0.52
Ohio    -0.56  1.97   1.39
Texas    0.09  0.28   0.77
Oregon   1.25  1.01  -1.30
In [200]: frame['e'].map(format)
  1. 排序:
In [201]: obj = pd.Series(range(4), index=['d', 'a', 'b', 'c'])
In [202]: obj.sort_index()  # 对索引进行排序
In [203]: frame = pd.DataFrame(np.arange(8).reshape((2, 4)),
   .....:                      index=['three', 'one'],
   .....:                      columns=['d', 'a', 'b', 'c'])
In [204]: frame.sort_index()
In [205]: frame.sort_index(axis=1)  # , ascending=False
In [205]: obj.sort_values()  # 对值进行排序
In [211]: frame = pd.DataFrame({'b': [4, 7, -3, 2], 'a': [0, 1, 0, 1]})
In [213]: frame.sort_values(by='b')
In [214]: frame.sort_values(by=['a', 'b'])
  1. 虽然许多pandas函数(如reindex)都要求标签唯一,但这并不是强制性的。当SeriesDataFrame的轴标签重复时,其处理会有不同:
obj = pd.Series(range(5), index=['a', 'a', 'b', 'b', 'c'])
obj.index.is_unique  # False
In [225]: obj['a']
Out[225]: 
a    0
a    1
dtype: int64
In [226]: obj['c']
Out[226]: 4
  1. 汇总和计算描述统计:
In [230]: df = pd.DataFrame([[1.4, np.nan], [7.1, -4.5],
   .....:                    [np.nan, np.nan], [0.75, -1.3]],
   .....:                   index=['a', 'b', 'c', 'd'],
   .....:                   columns=['one', 'two'])
In [232]: df.sum()  # NA值会自动被排除, 通过skipna选项可以禁用该功能
Out[232]: 
one    9.25
two   -5.80
dtype: float64
In [234]: df.mean(axis='columns', skipna=False)

描述和汇总统计

  1. Seriescorr方法用于计算两个Series中重叠的、非NA的、按索引对齐的值的相关系数。与此类似,cov用于计算协方差。
    DataFramecorrcov方法将以DataFrame的形式分别返回完整的相关系数或协方差矩阵。
    利用DataFramecorrwith方法,你可以计算其列或行跟另一个SeriesDataFrame之间的相关系数。传入一个Series将会返回一个相关系数值Series(针对各列进行计算)。传入一个DataFrame则会计算按列名配对的相关系数。
  2. unique返回未排序的唯一值数组;uniques = obj.unique()
    value_counts用于计算一个Series中各值出现的频率(降序排列的);obj.value_counts()
    value_counts还是一个顶级pandas方法,可用于任何数组或序列;
    isin用于判断矢量化集合的成员资格,可用于过滤Series中或DataFrame列中数据的子集: mask = obj.isin(['b', 'c'])
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值