您的位置:首页 > 编程语言 > Python开发

第3章 Pandas数据处理(3.4-3.5)_Python数据科学手册学习笔记

2018-10-02 16:31 676 查看

3.4 Pandas 数值运算方法

对于一元运算(像函数与三角函数),这些通用函数将在输出结果中保留索引和列标签; 而对于二元运算(如加法和乘法), Pandas在传递通用函数时会自动对齐索引进行计算. 这就意味着,保存数据内容和组合不同来源的数据—两处在NumPy数组中容易出错的地方,变成了Pandas的杀手锏.

3.4.1 通用函数: 保留索引

因为Pandas是建立在NumPy基础之上的, 所以NumPy的通用函数也同样适用于Pandas的Series和DataFrame.

import pandas as pd
import numpy as np
[/code]
rng = np.random.RandomState(42)
ser = pd.Series(rng.randint(0,10,4))
ser
[/code]
0    6
1    3
2    7
3    4
dtype: int32
df = pd.DataFrame(rng.randint(0,10,(3,4)),columns=['a','b','c','d'])   # 列标签只有4个,必须和数组列数量一致
df
[/code]
a b c d
0 6 9 2 6
1 7 4 3 7
2 7 2 5 4

3.4.2 通用函数: 索引对齐

当在两个Series或DataFrame对象进行二元计算时, Pandas会在计算过程中对齐两个对象的索引.

Series索引对齐

rk = pd.Series({'湖北':1234,'湖南':3242,'广东':3233},name='人口')    # Series有个name属性, 可以作为DataFrame列名称吗
mj = pd.Series({'湖北':123,'湖南':321,'山东':21},name='面积')
rk /mj
[/code]
山东          NaN
广东          NaN
湖北    10.032520
湖南    10.099688
dtype: float64

结果数组的索引是两个数组的并集. 也可以用另一种运算法则

rk.index | mj.index
[/code]
Index(['山东', '广东', '湖北', '湖南'], dtype='object')
a = pd.Series([2,4,6],index=[0,1,2])
b = pd.Series([1,3,5],index=[1,2,3])
a + b
# 为什么不把缺失的当0处理呢?
[/code]
0    NaN
1    5.0
2    9.0
3    NaN
dtype: float64
a | b   # a 并 b 表示什么意思
[/code]
0     True
1     True
2     True
3    False
dtype: bool
a & b  # a 交 b 表示什么意思
[/code]
0    False
1    False
2    False
3    False
dtype: bool
a ^ b
[/code]
0     True
1     True
2     True
3    False
dtype: bool
a * b
[/code]
0     NaN
1     4.0
2    18.0
3     NaN
dtype: float64
a.add(b,fill_value=0)  # 缺失值当0处理
[/code]
0    2.0
1    5.0
2    9.0
3    5.0
dtype: float64

DataFrame索引对齐
在计算两个DataFrame时, 类似的索引对齐规则同样会出现在共同列

A = pd.DataFrame(rng.randint(0,20,(2,2)),columns=list("AB"))
# 生成一个2*2的数组,数值都小于20. DataFrame列用list('AB')生成
B = pd.DataFrame(rng.randint(0,20,(3,3)),columns=list('ABC'))
print(A)
print('*'*20)
print(B)
print('*'*20)
print(A+B)
[/code]
A   B
0  1  11
1  5   1
********************
A   B   C
0   0  11  11
1  16   9  15
2  14  14  18
********************
A     B   C
0   1.0  22.0 NaN
1  21.0  10.0 NaN
2   NaN   NaN NaN

处理方法一: 用A中所有值得均值来填充缺失值. 计算A的均值需要用stack将二维数组压缩成一维数组

fill = A.stack().mean()
print(fill)
A.add(B,fill_value=fill)
# 比较下维度差,A数组缺的位置,都用均值填充
[/code]
4.5
A B C
0 1.0 22.0 15.5
1 21.0 10.0 19.5
2 18.5 18.5 22.5

Python运算符和Pandas方法的映射关系(下面必须空一行)

Python运算符 Pandas方法
+ add()
- sub(),subtract()
* mul(),multiply()
/ truediv(),div(),divide()
// floordiv()
% mod()
** pow()

3.4.3 通用函数: DataFrame与Series的运算

一个二维数组减去自身的一行数据

rng = np.random.RandomState(42)
a = rng.randint(10,size=(3,4))
print(type(a))
a
[/code]
<class 'numpy.ndarray'>

array([[6, 3, 7, 4],
[6, 9, 2, 6],
[7, 4, 3, 7]])
a - a[0]     # 0 表示第1行
[/code]
array([[ 0,  0,  0,  0],
[ 0,  6, -5,  2],
[ 1,  1, -4,  3]])
df = pd.DataFrame(a,columns=list('QRST'))
pd.DataFrame(a,columns=['q','r','s','t'])
pd.DataFrame(a,columns=('a','b','c','d'))
print(df)
[/code]
Q  R  S  T
0  6  3  7  4
1  6  9  2  6
2  7  4  3  7

一个DataFrame减去自身第1行

print(df-df.iloc[0])
print(df.subtract(df['R'],axis=0)   #此句报错, 可能是2.7 和3.+版本不兼容问题
[/code]
File "<ipython-input-49-0b4659832f8f>", line 2
print(df.subtract(df['R'],axis=0)
^
SyntaxError: unexpected EOF while parsing

3.5 处理缺失值

三种方法: null, NaN 和NA.

识别缺失值的方法: 通过一个覆盖全局的掩码表示缺失值, 另一种方法用一个标签纸表示.

3.5.2 Pandas的缺失值

Pandas最终选择用标签方法表示缺失值, 包括两种Python原有的缺失值: 浮点数据类型的NaN值, 以及Python的None对象. 后面我们将会发现,虽然这么做也有一些副作用, 但是在实际运用中够用.

None: Python对象类型的缺失值
- None是一个Python单体对象, 经常在代码中表示缺失值. 由于None是一个Python对象, 所以不能作为任何NumPy/Pandas数组类型的缺失值, 只能用于’object’数据类型(即由Python对象构成的数组). 什么意思?

x1 = np.array([1,None,3,4])
x1
[/code]
array([1, None, 3, 4], dtype=object)

使用Python对象构成的数组就意味着你对一个包含None的数组进行累计操作,如sum()和min(),通常会报错: 为什么?

x1.sum()
[/code]
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-52-0c8c176901d3> in <module>()
----> 1 x1.sum()
D:\Anaconda3\lib\site-packages\numpy\core\_methods.py in _sum(a, axis, dtype, out, keepdims)
30
31 def _sum(a, axis=None, dtype=None, out=None, keepdims=False):
---> 32     return umr_sum(a, axis, dtype, out, keepdims)
33
34 def _prod(a, axis=None, dtype=None, out=None, keepdims=False):

TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'

NaN: 数值类型的缺失值
- NaN(全程 Not a Number), 在任何系统中都兼容的特殊浮点数

x2 = np.array([1,np.nan,3,4])    # 要写成 np.nanx2.dtype
[/code]
dtype('float64')

NaN就像病毒一样会将它接触过的数据同化

1 + np.nan
[/code]
nan
0 + np.nan
[/code]
nan
x2.sum(),x2.max(),x2.min()
[/code]
(nan, nan, nan)

NumPy也提供了一些特殊的累计函数, 可以忽略缺失值的影响

np.nansum(x2), np.nanmin(x2), np.nanmax(x2)
#  x2.nansum()   报错
[/code]
(8.0, 1.0, 4.0)

Pandas中NaN与None的差异
- Pandas把它们看成是可以等价交换的, 在适当的时候会将两者进行替换.
- Pandas会将没有标签值得数据类型自动转换成NA

3.5.3 处理缺失值

发现,剔除,替换数据中的缺失值的方法:
- isnull(), 创建一个布尔类型的掩码标签缺失值
- notnull(), 与isnull()相反的操作
- dropna(), 返回一个剔除缺失值的数据
- fillna(), 返回一个填充了缺失值的数据副本

发现缺失值
- Pandas中有两种有效的方法可以发现缺失值: isnull()和notnull(),都返回布尔类型的掩码数据.

data = pd.Series([1,np.nan,'Hello',None])
data.isnull()
[/code]
0    False
1     True
2    False
3     True
dtype: bool
data[data.notnull()]
[/code]
0        1
2    Hello
dtype: object

剔除缺失值
- dropna(),剔除缺失值
- fillna(),填充缺失值

data.dropna()
[/code]
0        1
2    Hello
dtype: object

而在DataFrame上使用时需要设置一些参数

df = pd.DataFrame([[1,np.nan,2],
[2,3,5],
[np.nan,4,6]])
df
[/code]
0 1 2
0 1.0 NaN 2
1 2.0 3.0 5
2 NaN 4.0 6

没法从DataFrame中单独剔除一个值, 要么是剔除缺失值所在的整行,要么是整列. 根据实际需求.
- 默认情况下,dropna(),会剔除任何包含缺失值的整行数据

df.dropna()
[/code]
0 1 2
1 2.0 3.0 5

可以设置参数 axis=1 剔除任何包含缺失值的整列数据

df.dropna(axis=1)
[/code]
2
0 2
1 5
2 6
df[3] = np.nan    # 增加第4列,都为缺失值
df
[/code]
0 1 2 3
0 1.0 NaN 2 NaN
1 2.0 3.0 5 NaN
2 NaN 4.0 6 NaN
df.dropna(axis='columns',how='all')    #  如果某一个列全为缺失值,则删除 ,how的参数还可以等于any, 默认是any
[/code]
0 1 2
0 1.0 NaN 2
1 2.0 3.0 5
2 NaN 4.0 6

还可以通过参数thresh设置非缺失值的最小数量

填充缺失值

data = pd.Series([1,np.nan,2,None,3],index=list("abcde"))
data
[/code]
a    1.0
b    NaN
c    2.0
d    NaN
e    3.0
dtype: float64

用一个单独的值来填充缺失值,比如0或者100

data.fillna(0)
data.fillna(100)
[/code]
a      1.0
b    100.0
c      2.0
d    100.0
e      3.0
dtype: float64

可以用缺失值前面的有效值来从前往后填充

# 从前往后填充
data.fillna(method='ffill')
[/code]
a    1.0
b    1.0
c    2.0
d    2.0
e    3.0
dtype: float64
# 从后往前填充
data.fillna(method='bfill')
[/code]
a    1.0
b    2.0
c    2.0
d    3.0
e    3.0
dtype: float64

注意: 如果从前往后填充时, 需要填充的缺失值前面没有值, 那么它就仍然是缺失值.

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: