pandas缺失值处理-task01

1.缺失值种类

pandas中缺失值有三种,np.nan,None,及针对时间的缺失值类型,NaT,下面分开讲解这三种类型。

1.1 令人头秃的np.nan

首先是np.nan,由于pandas是基于Numpy的,Numpy的缺失值类型就是pandas最常见的缺失值类。但这个np.nan有大量问题,分下面几点。

  • 1.条件判断问题。np.nan什么也不等于,其实就是说它不等于自己,一个字符,‘a’只等于‘a’,但碰到np.nan,好了,你想循环一个列表,找出值为np.nan的列,使用 if i==np.nan:,不好意思,这个找不到,不可能有值等于np.nan的元素,你永远找不到,白瞎。
  • 2.数据类型变化问题。np.nan会改变该列的数据类型,np.nan是带有数据类型的,为float(64)。如果整形含有np.nan缺失值,那么该列会变为浮点型。如果是bool类型数据列,含有np.nan的地方,会自动填充为True。(正常来说应该变为False才对,这一点真的很难理解pandas的设计原理)。但当修改一个布尔列表时,将一个值赋值为np.nan的话,由于np.nan本身为浮点型数据,这样会改变列表类型为浮点型,原来True变为1.0,但赋值的地方为np.nan。对于字符型数据列,含有np.nan的话,由于字符型无法转为浮点型,所以该列的数据会变为Object类型。这是导致数据类型混乱的一大原因。

1.2 问题少一点的None

None比np.nan好一点,有如下几点:

  • 1.它可以等于自己。使用None==None,得到True
  • 2.本身布尔值为False,赋值给bool数据类型时,不会改变原数据类型。
    None空值类型,在数据列有数值类型数据时,None会变为np.nan
    只有当数据类型为object时,None会保持其数据类型。
  • None只有人为命名时,才会出现,因为pandas默认空值为np.nan

1.3 时间缺失项NaT

在时间类型中出现缺失值时,不管是np.nan还是None,都会转为NaT,这是时间缺失值的特殊缺失值类型。

2.新特性

2.1 Nullable数据类型

为了解决原pandas中缺失值数据类型造成的问题,pandas 1.0中新引进Int64,boolean,string,三种新数据类型,这三种数据类型叫做Nullable型数据,对缺失值有统一管理。

s_new = pd.Series([1, 2], dtype="Int64")
s_new[1] = np.nan
s_new

0       1
1    <NA>
dtype: Int64

在新数据类型下,出现缺失值会统一显示为,且数值类型不会改变

s_new[1] = None
s_new

0       1
1    <NA>
dtype: Int64

这三种数据类型的特点在于,有缺失值并不会改变其数据类型。
此外,对于stringl类型数据,和object类型的一点重要区别就在于,在调用字符方法后,string类型返回的是Nullable类型,object则会根据缺失类型和数据类型而改变

2.2 引入的新函数以进行数据转换

convert_dtypes方法
这个函数的功能往往就是在读取数据时,就把数据列转为Nullable类型,是1.0的新函数,使用十分方便。

pd.read_csv('data/table_missing.csv').convert_dtypes().dtypes
Out[73]:
School      string
Class       string
ID           Int64
Gender      string
Address     string
Height       Int64
Weight       Int64
Math       float64
Physics     string
dtype: object

3.缺失值的运算特性及填充

3.1 缺失值的统计运算特性

在进行数据统计时,使用求和函数,缺失值会被当为0计算,乘法则会当为1计算,其他情况会跳过缺失值。

3.2 缺失值的填充

  1. fillna方法
    (a)值填充与前后向填充(分别与ffill方法和bfill方法等价)
    值填充
df['Physics'].fillna('missing').head()
0         A+
1         B+
2         B+
3    missing
4         A-
Name: Physics, dtype: object

前后填充

#ffill 表示使用缺失值前一个非缺失值的数据填充,bfill则表示后一个值
df['Physics'].fillna(method='ffill').head()

(b)填充中的对齐特性
这里的对齐特性,指的是只填充返回结果中的列。

2.dropna方法
dropna方法有三个参数,轴的方向axis,删除方法how,和判断区域subset
(a)axis=0,1表示的按行看还是按列看

df_d = pd.DataFrame({
    
    'A':[np.nan,np.nan,np.nan],'B':[np.nan,3,2],'C':[3,2,1]})
df_d.dropna(axis=0)
	A	B	C
0	NaN	NaN	3
1	NaN	3.0	2
2	NaN	2.0	1

A  B  C

返回结果为空,因为每一行都有缺失值

(b) how参数(可以选all或者any,表示全为缺失去除和存在缺失去除)

In [89]:
df_d.dropna(axis=1,how='all')
Out[89]:
	B	C
0	NaN	3
1	3.0	2
2	2.0	1

(C)subset参数(即在某一组列范围中搜索缺失值)

In [90]:
df_d.dropna(axis=0,subset=['B','C'])
Out[90]:
	A	B	C
1	NaN	3.0	2
2	NaN	2.0	1

3.3线性插值及其他插值

(a)索引无关的线性插值
默认状态下,interpolate会对缺失的值进行线性插值

In [91]:
s = pd.Series([1,10,15,-5,-2,np.nan,np.nan,28])
s
Out[91]:
0     1.0
1    10.0
2    15.0
3    -5.0
4    -2.0
5     NaN
6     NaN
7    28.0
dtype: float64

这种插值方法与索引无关,会造成并不是线性的结果

s.interpolate()
Out[92]:
0     1.0
1    10.0
2    15.0
3    -5.0
4    -2.0
5     8.0
6    18.0
7    28.0
dtype: float64

加入时间索引或者索引,会取得真的线性插值结果

s.interpolate(method='index').plot()

索引为时间时

s_t = pd.Series([0,np.nan,10]
        ,index=[pd.Timestamp('2012-05-01'),pd.Timestamp('2012-05-07'),pd.Timestamp('2012-06-03')])
s_t.interpolate(method='time')
  • 高级插值方法
    此处的高级指的是与线性插值相比较,例如样条插值、多项式插值、阿基玛插值等(需要安装Scipy)。
ser = pd.Series(np.arange(1, 10.1, .25) ** 2 + np.random.randn(37))
missing = np.array([4, 13, 14, 15, 16, 17, 18, 20, 29])
ser[missing] = np.nan
methods = ['linear', 'quadratic', 'cubic']
df = pd.DataFrame({
    
    m: ser.interpolate(method=m) for m in methods})
df.plot()

插值的一些参数设置
(a)limit表示最多插入多少个

s = pd.Series([1,np.nan,np.nan,np.nan,5])
s.interpolate(limit=2)

0    1.0
1    2.0
2    3.0
3    NaN
4    5.0
dtype: float64

(b)limit_direction表示插值方向,可选forward,backward,both,默认前向

s = pd.Series([np.nan,np.nan,1,np.nan,np.nan,np.nan,5,np.nan,np.nan,])
s.interpolate(limit_direction='backward')
0    1.0
1    1.0
2    1.0
3    2.0
4    3.0
5    4.0
6    5.0
7    NaN
8    NaN
dtype: float64

(c)插值区域参数设置

s = pd.Series([np.nan,np.nan,1,np.nan,np.nan,np.nan,5,np.nan,np.nan,])
s.interpolate(limit_area='inside')

0    NaN
1    NaN
2    1.0
3    2.0
4    3.0
5    4.0
6    5.0
7    NaN
8    NaN
dtype: float64

``None’’:没有填充限制。‘inside’:仅填充有效值包围的NaN(插)。‘外部’:仅在有效值之外填充NaN(外推)。

参考

[1] datawhalechina/joyful-pandas

猜你喜欢

转载自blog.csdn.net/hu_hao/article/details/106892429