Working with missing data¶
在本节中,我们将讨论pandas中的缺失(也称为NA)值。
注意
在内部使用NaN
表示丢失数据的选择在很大程度上是出于简单性和性能原因。它与MaskedArray方法不同,例如scikits.timeseries
。我们希望NumPy很快能够提供一个原生NA类型的解决方案(类似于R)的性能足以用于熊猫。
有关某些高级策略,请参阅cookbook
Missing data basics¶
When / why does data become missing?¶
有些人可能会对我们使用缺少的产生疑惑。“缺少”我们只是指null或“不存在为什么原因”。许多数据集只是带有缺失数据到达,或者是因为它存在并且没有被收集或者它从来不存在。例如,在财务时间系列的集合中,某些时间系列可能在不同的日期开始。因此,在开始日期之前的值通常将被标记为缺失。
在pandas中,丢失数据引入到数据集中的最常见方法之一是通过重新索引。例如
In [1]: df = pd.DataFrame(np.random.randn(5, 3), index=['a', 'c', 'e', 'f', 'h'],
...: columns=['one', 'two', 'three'])
...:
In [2]: df['four'] = 'bar'
In [3]: df['five'] = df['one'] > 0
In [4]: df
Out[4]:
one two three four five
a 0.469112 -0.282863 -1.509059 bar True
c -1.135632 1.212112 -0.173215 bar False
e 0.119209 -1.044236 -0.861849 bar True
f -2.104569 -0.494929 1.071804 bar False
h 0.721555 -0.706771 -1.039575 bar True
In [5]: df2 = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
In [6]: df2
Out[6]:
one two three four five
a 0.469112 -0.282863 -1.509059 bar True
b NaN NaN NaN NaN NaN
c -1.135632 1.212112 -0.173215 bar False
d NaN NaN NaN NaN NaN
e 0.119209 -1.044236 -0.861849 bar True
f -2.104569 -0.494929 1.071804 bar False
g NaN NaN NaN NaN NaN
h 0.721555 -0.706771 -1.039575 bar True
Values considered “missing”¶
由于数据有多种形式和形式,pandas旨在灵活处理丢失的数据。由于计算速度和方便性的原因,NaN
是默认的缺失值标记,我们需要能够使用不同类型的数据轻松检测此值:浮点,整数,布尔值和常规对象。然而,在许多情况下,Python None
将出现,我们希望也考虑“missing”或“null”。
注意
在版本v0.10.0 inf
和-inf
之前,在计算中也被认为是“null”。默认情况下不再是这种情况;请使用mode.use_inf_as_null
选项恢复它。
pandas为了更好的处理缺失值(包括不同列的不同类型), 提供了 isnull()
和 notnull()
函数, 这两种方法都可以用在 Series
和 DataFrame
对象上:
In [7]: df2['one']
Out[7]:
a 0.469112
b NaN
c -1.135632
d NaN
e 0.119209
f -2.104569
g NaN
h 0.721555
Name: one, dtype: float64
In [8]: pd.isnull(df2['one'])
Out[8]:
a False
b True
c False
d True
e False
f False
g True
h False
Name: one, dtype: bool
In [9]: df2['four'].notnull()
Out[9]:
a True
b False
c True
d False
e True
f True
g False
h True
Name: four, dtype: bool
In [10]: df2.isnull()
Out[10]:
one two three four five
a False False False False False
b True True True True True
c False False False False False
d True True True True True
e False False False False False
f False False False False False
g True True True True True
h False False False False False
警告
必须注意,在python(和numpy)中,nan's
不比较相等,但None's
do。Note that Pandas/numpy uses the fact that np.nan != np.nan
, and treats None
like np.nan
.
In [11]: None == None
Out[11]: True
In [12]: np.nan == np.nan
Out[12]: False
因此,与上述相比,标量等式比较与None/np.nan
不提供有用的信息。
In [13]: df2['one'] == np.nan
Out[13]:
a False
b False
c False
d False
e False
f False
g False
h False
Name: one, dtype: bool
Datetimes¶
对于datetime64 [ns]类型,NaT
表示缺少的值。这是一个伪本地的哨兵值,可以用单数dtype(datetime64 [ns])中的numpy表示。pandas对象提供NaT
和NaN
之间的相互兼容性。
In [14]: df2 = df.copy()
In [15]: df2['timestamp'] = pd.Timestamp('20120101')
In [16]: df2
Out[16]:
one two three four five timestamp
a 0.469112 -0.282863 -1.509059 bar True 2012-01-01
c -1.135632 1.212112 -0.173215 bar False 2012-01-01
e 0.119209 -1.044236 -0.861849 bar True 2012-01-01
f -2.104569 -0.494929 1.071804 bar False 2012-01-01
h 0.721555 -0.706771 -1.039575 bar True 2012-01-01
In [17]: df2.ix[['a','c','h'],['one','timestamp']] = np.nan
In [18]: df2
Out[18]:
one two three four five timestamp
a NaN -0.282863 -1.509059 bar True NaT
c NaN 1.212112 -0.173215 bar False NaT
e 0.119209 -1.044236 -0.861849 bar True 2012-01-01
f -2.104569 -0.494929 1.071804 bar False 2012-01-01
h NaN -0.706771 -1.039575 bar True NaT
In [19]: df2.get_dtype_counts()
Out[19]:
bool 1
datetime64[ns] 1
float64 3
object 1
dtype: int64
Inserting missing data¶
您可以通过简单地分配到容器来插入缺失值。使用的实际缺失值将基于dtype进行选择。
例如,无论选择的缺少值类型如何,数值型将始终使用NaN
:
In [20]: s = pd.Series([1, 2, 3])
In [21]: s.loc[0] = None
In [22]: s
Out[22]:
0 NaN
1 2.0
2 3.0
dtype: float64
同样,datetime对象将始终使用NaT
。
对于object类型,pandas将使用给定的值:
In [23]: s = pd.Series(["a", "b", "c"])
In [24]: s.loc[0] = None
In [25]: s.loc[1] = np.nan
In [26]: s
Out[26]:
0 None
1 NaN
2 c
dtype: object
Calculations with missing data¶
缺失值通过pandas对象之间的算术运算自然传播。
In [27]: a
Out[27]:
one two
a NaN -0.282863
c NaN 1.212112
e 0.119209 -1.044236
f -2.104569 -0.494929
h -2.104569 -0.706771
In [28]: b
Out[28]:
one two three
a NaN -0.282863 -1.509059
c NaN 1.212112 -0.173215
e 0.119209 -1.044236 -0.861849
f -2.104569 -0.494929 1.071804
h NaN -0.706771 -1.039575
In [29]: a + b
Out[29]:
one three two
a NaN NaN -0.565727
c NaN NaN 2.424224
e 0.238417 NaN -2.088472
f -4.209138 NaN -0.989859
h NaN NaN -1.413542
在data structure overview(此处列出here和here)中讨论的描述性统计和计算方法都是为了记录丢失的数据。例如:
- 当对数据求和时,NA(缺失)值将被视为零
- 如果数据都是NA,则结果将是NA
- cumsum和cumprod等方法忽略NA值,但在生成的数组中保留它们
In [30]: df
Out[30]:
one two three
a NaN -0.282863 -1.509059
c NaN 1.212112 -0.173215
e 0.119209 -1.044236 -0.861849
f -2.104569 -0.494929 1.071804
h NaN -0.706771 -1.039575
In [31]: df['one'].sum()
Out[31]: -1.9853605075978744
In [32]: df.mean(1)
Out[32]:
a -0.895961
c 0.519449
e -0.595625
f -0.509232
h -0.873173
dtype: float64
In [33]: df.cumsum()
Out[33]:
one two three
a NaN -0.282863 -1.509059
c NaN 0.929249 -1.682273
e 0.119209 -0.114987 -2.544122
f -1.985361 -0.609917 -1.472318
h NaN -1.316688 -2.511893
NA values in GroupBy¶
GroupBy中的NA组将自动排除。此行为与R一致,例如:
In [34]: df
Out[34]:
one two three
a NaN -0.282863 -1.509059
c NaN 1.212112 -0.173215
e 0.119209 -1.044236 -0.861849
f -2.104569 -0.494929 1.071804
h NaN -0.706771 -1.039575
In [35]: df.groupby('one').mean()
Out[35]:
two three
one
-2.104569 -0.494929 1.071804
0.119209 -1.044236 -0.861849
有关详细信息,请参阅here部分。
Cleaning / filling missing data¶
pandas对象配备了各种数据处理方法来处理丢失的数据。
Filling missing values: fillna¶
fillna函数可以通过两种方式“填充”NA值与非空数据,我们说明:
将NA替换为标量值
In [36]: df2
Out[36]:
one two three four five timestamp
a NaN -0.282863 -1.509059 bar True NaT
c NaN 1.212112 -0.173215 bar False NaT
e 0.119209 -1.044236 -0.861849 bar True 2012-01-01
f -2.104569 -0.494929 1.071804 bar False 2012-01-01
h NaN -0.706771 -1.039575 bar True NaT
In [37]: df2.fillna(0)
Out[37]:
one two three four five timestamp
a 0.000000 -0.282863 -1.509059 bar True 1970-01-01
c 0.000000 1.212112 -0.173215 bar False 1970-01-01
e 0.119209 -1.044236 -0.861849 bar True 2012-01-01
f -2.104569 -0.494929 1.071804 bar False 2012-01-01
h 0.000000 -0.706771 -1.039575 bar True 1970-01-01
In [38]: df2['four'].fillna('missing')
Out[38]:
a bar
c bar
e bar
f bar
h bar
Name: four, dtype: object
向前或向后填充间隙
使用与reindexing相同的填充参数,我们可以向前或向后传播非空值:
In [39]: df
Out[39]:
one two three
a NaN -0.282863 -1.509059
c NaN 1.212112 -0.173215
e 0.119209 -1.044236 -0.861849
f -2.104569 -0.494929 1.071804
h NaN -0.706771 -1.039575
In [40]: df.fillna(method='pad')
Out[40]:
one two three
a NaN -0.282863 -1.509059
c NaN 1.212112 -0.173215
e 0.119209 -1.044236 -0.861849
f -2.104569 -0.494929 1.071804
h -2.104569 -0.706771 -1.039575
控制填充的缺失值数量
如果我们只想让连续的间隙填充到一定数量的数据点,我们可以使用limit关键字:
In [41]: df
Out[41]:
one two three
a NaN -0.282863 -1.509059
c NaN 1.212112 -0.173215
e NaN NaN NaN
f NaN NaN NaN
h NaN -0.706771 -1.039575
In [42]: df.fillna(method='pad', limit=1)
Out[42]:
one two three
a NaN -0.282863 -1.509059
c NaN 1.212112 -0.173215
e NaN 1.212112 -0.173215
f NaN NaN NaN
h NaN -0.706771 -1.039575
为了提醒您,这些是可用的填充方法:
方法 | 行动 |
---|---|
pad / ffill | 向前填充值 |
bfill / backfill | 向后填充值 |
使用时间序列数据,使用pad / ffill非常常见,因此“最后已知值”在每个时间点都可用。
ffill()
函数等效于fillna(method='ffill')
和bfill()
等效于fillna(method='bfill')
Filling with a PandasObject¶
版本0.12中的新功能。
你也可以使用可以对齐的dict或者系列。系列的dict或index的标签必须与您要填充的框架的列匹配。这种情况的用法是用该列的平均值填充DataFrame。
In [43]: dff = pd.DataFrame(np.random.randn(10,3), columns=list('ABC'))
In [44]: dff.iloc[3:5,0] = np.nan
In [45]: dff.iloc[4:6,1] = np.nan
In [46]: dff.iloc[5:8,2] = np.nan
In [47]: dff
Out[47]:
A B C
0 0.271860 -0.424972 0.567020
1 0.276232 -1.087401 -0.673690
2 0.113648 -1.478427 0.524988
3 NaN 0.577046 -1.715002
4 NaN NaN -1.157892
5 -1.344312 NaN NaN
6 -0.109050 1.643563 NaN
7 0.357021 -0.674600 NaN
8 -0.968914 -1.294524 0.413738
9 0.276662 -0.472035 -0.013960
In [48]: dff.fillna(dff.mean())
Out[48]:
A B C
0 0.271860 -0.424972 0.567020
1 0.276232 -1.087401 -0.673690
2 0.113648 -1.478427 0.524988
3 -0.140857 0.577046 -1.715002
4 -0.140857 -0.401419 -1.157892
5 -1.344312 -0.401419 -0.293543
6 -0.109050 1.643563 -0.293543
7 0.357021 -0.674600 -0.293543
8 -0.968914 -1.294524 0.413738
9 0.276662 -0.472035 -0.013960
In [49]: dff.fillna(dff.mean()['B':'C'])
Out[49]:
A B C
0 0.271860 -0.424972 0.567020
1 0.276232 -1.087401 -0.673690
2 0.113648 -1.478427 0.524988
3 NaN 0.577046 -1.715002
4 NaN -0.401419 -1.157892
5 -1.344312 -0.401419 -0.293543
6 -0.109050 1.643563 -0.293543
7 0.357021 -0.674600 -0.293543
8 -0.968914 -1.294524 0.413738
9 0.276662 -0.472035 -0.013960
版本0.13中的新功能。
与上面的结果相同,但是对齐了“fill”值,这是一个在这种情况下的系列。
In [50]: dff.where(pd.notnull(dff), dff.mean(), axis='columns')
Out[50]:
A B C
0 0.271860 -0.424972 0.567020
1 0.276232 -1.087401 -0.673690
2 0.113648 -1.478427 0.524988
3 -0.140857 0.577046 -1.715002
4 -0.140857 -0.401419 -1.157892
5 -1.344312 -0.401419 -0.293543
6 -0.109050 1.643563 -0.293543
7 0.357021 -0.674600 -0.293543
8 -0.968914 -1.294524 0.413738
9 0.276662 -0.472035 -0.013960
Dropping axis labels with missing data: dropna¶
您可能希望简单地从数据集中排除涉及缺失数据的标签。为此,请使用dropna方法:
In [51]: df
Out[51]:
one two three
a NaN -0.282863 -1.509059
c NaN 1.212112 -0.173215
e NaN 0.000000 0.000000
f NaN 0.000000 0.000000
h NaN -0.706771 -1.039575
In [52]: df.dropna(axis=0)
Out[52]:
Empty DataFrame
Columns: [one, two, three]
Index: []
In [53]: df.dropna(axis=1)
Out[53]:
two three
a -0.282863 -1.509059
c 1.212112 -0.173215
e 0.000000 0.000000
f 0.000000 0.000000
h -0.706771 -1.039575
In [54]: df['one'].dropna()
Out[54]: Series([], Name: one, dtype: float64)
Series.dropna是一个更简单的方法,因为它只有一个轴要考虑。DataFrame.dropna有比Series.dropna更多的选项,可以在API中检查in the API
Interpolation¶
版本0.13.0中的新功能: interpolate()
和interpolate()
更新了插值方法和功能。
版本0.17.0中的新功能:添加了limit_direction
关键字参数。
Series和Dataframe对象都有一个interpolate
方法,默认情况下,在缺失的数据点执行线性插值。
In [55]: ts
Out[55]:
2000-01-31 0.469112
2000-02-29 NaN
2000-03-31 NaN
2000-04-28 NaN
2000-05-31 NaN
2000-06-30 NaN
2000-07-31 NaN
...
2007-10-31 -3.305259
2007-11-30 -5.485119
2007-12-31 -6.854968
2008-01-31 -7.809176
2008-02-29 -6.346480
2008-03-31 -8.089641
2008-04-30 -8.916232
Freq: BM, dtype: float64
In [56]: ts.count()
Out[56]: 61
In [57]: ts.interpolate().count()
Out[57]: 100
In [58]: ts.interpolate().plot()
Out[58]: <matplotlib.axes._subplots.AxesSubplot at 0x7ff2667af150>
可通过method
关键字获得索引感知插值:
In [59]: ts2
Out[59]:
2000-01-31 0.469112
2000-02-29 NaN
2002-07-31 -5.689738
2005-01-31 NaN
2008-04-30 -8.916232
dtype: float64
In [60]: ts2.interpolate()
Out[60]:
2000-01-31 0.469112
2000-02-29 -2.610313
2002-07-31 -5.689738
2005-01-31 -7.302985
2008-04-30 -8.916232
dtype: float64
In [61]: ts2.interpolate(method='time')
Out[61]:
2000-01-31 0.469112
2000-02-29 0.273272
2002-07-31 -5.689738
2005-01-31 -7.095568
2008-04-30 -8.916232
dtype: float64
对于浮点索引,请使用method='values'
:
In [62]: ser
Out[62]:
0.0 0.0
1.0 NaN
10.0 10.0
dtype: float64
In [63]: ser.interpolate()
Out[63]:
0.0 0.0
1.0 5.0
10.0 10.0
dtype: float64
In [64]: ser.interpolate(method='values')
Out[64]:
0.0 0.0
1.0 1.0
10.0 10.0
dtype: float64
您还可以使用DataFrame插值:
In [65]: df = pd.DataFrame({'A': [1, 2.1, np.nan, 4.7, 5.6, 6.8],
....: 'B': [.25, np.nan, np.nan, 4, 12.2, 14.4]})
....:
In [66]: df
Out[66]:
A B
0 1.0 0.25
1 2.1 NaN
2 NaN NaN
3 4.7 4.00
4 5.6 12.20
5 6.8 14.40
In [67]: df.interpolate()
Out[67]:
A B
0 1.0 0.25
1 2.1 1.50
2 3.4 2.75
3 4.7 4.00
4 5.6 12.20
5 6.8 14.40
method
参数允许访问fancier插值方法。如果您安装了scipy,则可以将1-d插值程序的名称设置为method
。有关详细信息,请参阅完整的scipy插值文档和参考指南。适当的插值方法将取决于您使用的数据类型。
- 如果你正在处理一个以递增的速度增长的时间序列,则
method='quadratic'
可能是适当的。 - 如果你有近似累积分布函数的值,那么
method='pchip'
应该工作得很好。 - 要以平滑绘图的目标填充缺失值,请使用
method='akima'
。
警告
这些方法需要scipy
。
In [68]: df.interpolate(method='barycentric')
Out[68]:
A B
0 1.00 0.250
1 2.10 -7.660
2 3.53 -4.515
3 4.70 4.000
4 5.60 12.200
5 6.80 14.400
In [69]: df.interpolate(method='pchip')
Out[69]:
A B
0 1.00000 0.250000
1 2.10000 0.672808
2 3.43454 1.928950
3 4.70000 4.000000
4 5.60000 12.200000
5 6.80000 14.400000
In [70]: df.interpolate(method='akima')
Out[70]:
A B
0 1.000000 0.250000
1 2.100000 -0.873316
2 3.406667 0.320034
3 4.700000 4.000000
4 5.600000 12.200000
5 6.800000 14.400000
当通过多项式或样条逼近进行插值时,还必须指定近似的次数或次数:
In [71]: df.interpolate(method='spline', order=2)
Out[71]:
A B
0 1.000000 0.250000
1 2.100000 -0.428598
2 3.404545 1.206900
3 4.700000 4.000000
4 5.600000 12.200000
5 6.800000 14.400000
In [72]: df.interpolate(method='polynomial', order=2)
Out[72]:
A B
0 1.000000 0.250000
1 2.100000 -4.161538
2 3.547059 -2.911538
3 4.700000 4.000000
4 5.600000 12.200000
5 6.800000 14.400000
比较几种方法:
In [73]: np.random.seed(2)
In [74]: ser = pd.Series(np.arange(1, 10.1, .25)**2 + np.random.randn(37))
In [75]: bad = np.array([4, 13, 14, 15, 16, 17, 18, 20, 29])
In [76]: ser[bad] = np.nan
In [77]: methods = ['linear', 'quadratic', 'cubic']
In [78]: df = pd.DataFrame({m: ser.interpolate(method=m) for m in methods})
In [79]: df.plot()
Out[79]: <matplotlib.axes._subplots.AxesSubplot at 0x7ff2666771d0>
另一个用例是在新值处的插值。假设你有一些分布的100个观察。让我们假设你对中间发生的事情特别感兴趣。您可以混合使用pandas'reindex
和interpolate
方法在新值处插值。
In [80]: ser = pd.Series(np.sort(np.random.uniform(size=100)))
# interpolate at new_index
In [81]: new_index = ser.index | pd.Index([49.25, 49.5, 49.75, 50.25, 50.5, 50.75])
In [82]: interp_s = ser.reindex(new_index).interpolate(method='pchip')
In [83]: interp_s[49:51]
Out[83]:
49.00 0.471410
49.25 0.476841
49.50 0.481780
49.75 0.485998
50.00 0.489266
50.25 0.491814
50.50 0.493995
50.75 0.495763
51.00 0.497074
dtype: float64
Interpolation Limits¶
与其他Pandas填充方法一样,interpolate
接受一个limit
关键字参数。使用此参数限制连续插值的数量,对于距离上次有效观测值过远的插值,保留NaN
值:
In [84]: ser = pd.Series([np.nan, np.nan, 5, np.nan, np.nan, np.nan, 13])
In [85]: ser.interpolate(limit=2)
Out[85]:
0 NaN
1 NaN
2 5.0
3 7.0
4 9.0
5 NaN
6 13.0
dtype: float64
默认情况下,limit
适用于正向,因此在非NaN
值后只能填充NaN
值。If you provide 'backward'
or 'both'
for the limit_direction
keyword argument, you can fill NaN
values before non-NaN
values, or both before and after non-NaN
values, respectively:
In [86]: ser.interpolate(limit=1) # limit_direction == 'forward'
Out[86]:
0 NaN
1 NaN
2 5.0
3 7.0
4 NaN
5 NaN
6 13.0
dtype: float64
In [87]: ser.interpolate(limit=1, limit_direction='backward')
Out[87]:
0 NaN
1 5.0
2 5.0
3 NaN
4 NaN
5 11.0
6 13.0
dtype: float64
In [88]: ser.interpolate(limit=1, limit_direction='both')
Out[88]:
0 NaN
1 5.0
2 5.0
3 7.0
4 NaN
5 11.0
6 13.0
dtype: float64
Replacing Generic Values¶
通常我们想用其他值替换任意值。v0.8中的新增功能是Series / DataFrame中的replace
方法,它提供了一种高效而灵活的方法来执行此类替换。
对于系列,可以使用另一个值替换单个值或值列表:
In [89]: ser = pd.Series([0., 1., 2., 3., 4.])
In [90]: ser.replace(0, 5)
Out[90]:
0 5.0
1 1.0
2 2.0
3 3.0
4 4.0
dtype: float64
您可以使用其他值列表替换值列表:
In [91]: ser.replace([0, 1, 2, 3, 4], [4, 3, 2, 1, 0])
Out[91]:
0 4.0
1 3.0
2 2.0
3 1.0
4 0.0
dtype: float64
您还可以指定映射dict:
In [92]: ser.replace({0: 10, 1: 100})
Out[92]:
0 10.0
1 100.0
2 2.0
3 3.0
4 4.0
dtype: float64
对于DataFrame,您可以按列指定单个值:
In [93]: df = pd.DataFrame({'a': [0, 1, 2, 3, 4], 'b': [5, 6, 7, 8, 9]})
In [94]: df.replace({'a': 0, 'b': 5}, 100)
Out[94]:
a b
0 100 100
1 1 6
2 2 7
3 3 8
4 4 9
您可以将所有给定的值视为缺失并对其进行插值,而不是替换为指定的值:
In [95]: ser.replace([1, 2, 3], method='pad')
Out[95]:
0 0.0
1 0.0
2 0.0
3 0.0
4 4.0
dtype: float64
String/Regular Expression Replacement¶
注意
以r
字符为前缀的Python字符串,如r'hello world'
是所谓的“raw”字符串。他们有不同的反斜杠语义比没有这个前缀的字符串。原始字符串中的反斜杠将被解释为转义的反斜杠,例如r'\' == '\\' t0>。
如果这不清楚,您应该阅读他们。
用nan
(str - > str)替换'。'
In [96]: d = {'a': list(range(4)), 'b': list('ab..'), 'c': ['a', 'b', np.nan, 'd']}
In [97]: df = pd.DataFrame(d)
In [98]: df.replace('.', np.nan)
Out[98]:
a b c
0 0 a a
1 1 b b
2 2 NaN NaN
3 3 NaN d
现在使用正则表达式删除周围的空格(regex - > regex)
In [99]: df.replace(r'\s*\.\s*', np.nan, regex=True)
Out[99]:
a b c
0 0 a a
1 1 b b
2 2 NaN NaN
3 3 NaN d
替换几个不同的值(list - > list)
In [100]: df.replace(['a', '.'], ['b', np.nan])
Out[100]:
a b c
0 0 b b
1 1 b b
2 2 NaN NaN
3 3 NaN d
regex列表 - > regex列表
In [101]: df.replace([r'\.', r'(a)'], ['dot', '\1stuff'], regex=True)
Out[101]:
a b c
0 0 stuff stuff
1 1 b b
2 2 dot NaN
3 3 dot d
只搜索列'b'
(dict - > dict)
In [102]: df.replace({'b': '.'}, {'b': np.nan})
Out[102]:
a b c
0 0 a a
1 1 b b
2 2 NaN NaN
3 3 NaN d
与上一个示例相同,但使用正则表达式进行搜索(dict的regex - > dict)
In [103]: df.replace({'b': r'\s*\.\s*'}, {'b': np.nan}, regex=True)
Out[103]:
a b c
0 0 a a
1 1 b b
2 2 NaN NaN
3 3 NaN d
您可以传递使用regex=True
的正则表达式的嵌套字典
In [104]: df.replace({'b': {'b': r''}}, regex=True)
Out[104]:
a b c
0 0 a a
1 1 b
2 2 . NaN
3 3 . d
或者你可以像这样传递嵌套字典
In [105]: df.replace(regex={'b': {r'\s*\.\s*': np.nan}})
Out[105]:
a b c
0 0 a a
1 1 b b
2 2 NaN NaN
3 3 NaN d
你也可以在替换时使用正则表达式匹配的组(正则表达式的dict - >正则表达式的dict),这也适用于列表
In [106]: df.replace({'b': r'\s*(\.)\s*'}, {'b': r'\1ty'}, regex=True)
Out[106]:
a b c
0 0 a a
1 1 b b
2 2 .ty NaN
3 3 .ty d
您可以传递正则表达式列表,其中匹配的那些将被替换为标量(regex - > regex列表)
In [107]: df.replace([r'\s*\.\s*', r'a|b'], np.nan, regex=True)
Out[107]:
a b c
0 0 NaN NaN
1 1 NaN NaN
2 2 NaN NaN
3 3 NaN d
所有正则表达式示例也可以使用to_replace
参数作为regex
参数传递。在这种情况下,value
参数必须通过名称显式传递,或regex
必须是嵌套字典。在这种情况下,上一个示例将是
In [108]: df.replace(regex=[r'\s*\.\s*', r'a|b'], value=np.nan)
Out[108]:
a b c
0 0 NaN NaN
1 1 NaN NaN
2 2 NaN NaN
3 3 NaN d
如果您不想在每次要使用正则表达式时传递regex=True
,这都很方便。
注意
在上述replace
示例的任何地方,您看到正则表达式编译的正则表达式也是有效的。
Numeric Replacement¶
类似于DataFrame.fillna
In [109]: df = pd.DataFrame(np.random.randn(10, 2))
In [110]: df[np.random.rand(df.shape[0]) > 0.5] = 1.5
In [111]: df.replace(1.5, np.nan)
Out[111]:
0 1
0 -0.844214 -1.021415
1 0.432396 -0.323580
2 0.423825 0.799180
3 1.262614 0.751965
4 NaN NaN
5 NaN NaN
6 -0.498174 -1.060799
7 0.591667 -0.183257
8 1.019855 -1.482465
9 NaN NaN
通过列表替换多个值也是如此
In [112]: df00 = df.values[0, 0]
In [113]: df.replace([1.5, df00], [np.nan, 'a'])
Out[113]:
0 1
0 a -1.021415
1 0.432396 -0.323580
2 0.423825 0.799180
3 1.26261 0.751965
4 NaN NaN
5 NaN NaN
6 -0.498174 -1.060799
7 0.591667 -0.183257
8 1.01985 -1.482465
9 NaN NaN
In [114]: df[1].dtype
Out[114]: dtype('float64')
你也可以在DataFrame上操作
In [115]: df.replace(1.5, np.nan, inplace=True)
警告
替换多个bool
或datetime64
对象时,replace
(to_replace
)的第一个参数必须匹配值为替换类型。例如,
s = pd.Series([True, False, True])
s.replace({'a string': 'new value', True: False}) # raises
TypeError: Cannot compare types 'ndarray(dtype=bool)' and 'str'
将会产生TypeError
,因为dict
键之一不是用于替换的正确类型。
但是,当替换单个对象时,
In [116]: s = pd.Series([True, False, True])
In [117]: s.replace('a string', 'another string')
Out[117]:
0 True
1 False
2 True
dtype: bool
原始的NDFrame
对象将不被触摸。我们正在努力统一这个API,但是出于向后兼容性的原因,我们不能打破后面的行为。有关详细信息,请参阅GH6354。
Missing data casting rules and indexing¶
虽然pandas支持存储整数和布尔类型的数组,但这些类型不能存储缺失的数据。直到我们可以在NumPy中切换到使用本地NA类型,我们已经建立了一些“转换规则”,当重建索引将导致丢失的数据被引入,例如,一个Series或DataFrame。他们来了:
数据类型 | 投放到 |
---|---|
整数 | 浮动 |
布尔 | 目的 |
浮动 | 没有演员 |
目的 | 没有演员 |
例如:
In [118]: s = pd.Series(np.random.randn(5), index=[0, 2, 4, 6, 7])
In [119]: s > 0
Out[119]:
0 True
2 True
4 True
6 True
7 True
dtype: bool
In [120]: (s > 0).dtype
Out[120]: dtype('bool')
In [121]: crit = (s > 0).reindex(list(range(8)))
In [122]: crit
Out[122]:
0 True
1 NaN
2 True
3 NaN
4 True
5 NaN
6 True
7 True
dtype: object
In [123]: crit.dtype
Out[123]: dtype('O')
如果您尝试使用对象数组(即使它包含布尔值)而不是布尔数组来从ndarray获取或设置值(例如,根据某些条件选择值),NumPy通常会提示。如果布尔向量包含NA,将生成异常:
In [124]: reindexed = s.reindex(list(range(8))).fillna(0)
In [125]: reindexed[crit]
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-125-2da204ed1ac7> in <module>()
----> 1 reindexed[crit]
/home/joris/scipy/pandas/pandas/core/series.pyc in __getitem__(self, key)
639 key = list(key)
640
--> 641 if com.is_bool_indexer(key):
642 key = check_bool_indexer(self.index, key)
643
/home/joris/scipy/pandas/pandas/core/common.pyc in is_bool_indexer(key)
199 if not lib.is_bool_array(key):
200 if isnull(key).any():
--> 201 raise ValueError('cannot index with vector containing '
202 'NA / NaN values')
203 return False
ValueError: cannot index with vector containing NA / NaN values
但是,这些可以使用fillna填充,它会工作正常:
In [126]: reindexed[crit.fillna(False)]
Out[126]:
0 0.126504
2 0.696198
4 0.697416
6 0.601516
7 0.003659
dtype: float64
In [127]: reindexed[crit.fillna(True)]
Out[127]:
0 0.126504
1 0.000000
2 0.696198
3 0.000000
4 0.697416
5 0.000000
6 0.601516
7 0.003659
dtype: float64