当前的pandas版本:0.22
我有一个SparseDataFrame。
A = pd.SparseDataFrame(
[['a',0,0,'b'],
[0,0,0,'c'],
[0,0,0,0],
[0,0,0,'a']])
A
0 1 2 3
0 a 0 0 b
1 0 0 0 c
2 0 0 0 0
3 0 0 0 a
现在,填充值为0
。但是,我想将fill_values更改为np.nan
。我的第一直觉是打电话给replace
:
A.replace(0, np.nan)
但是这给了
TypeError: cannot convert int to an sparseblock
这并不能帮助我理解我做错了什么。
我知道我能做到
A.to_dense().replace(0, np.nan).to_sparse()
但是有更好的方法吗?或者我对稀疏数据帧的基本理解存在缺陷?
答案 0 :(得分:14)
tl; dr :这绝对是一个错误 但请继续阅读,还有更多......
以下所有内容适用于pandas 0.20.3,但不适用于任何较新版本:
A.replace(0,np.nan)
A.replace({0:np.nan})
A.replace([0],[np.nan])
等等......(你明白了)。
(从现在开始,所有代码都是用pandas 0.20.3完成的。)
然而,那些(以及我尝试过的大部分解决方法)都有效,因为我们不小心做错了。如果我们这样做你会立刻猜到:
A.density
1.0
这个SparseDataFrame实际上很密集!
我们可以通过传递default_fill_value=0
:
A = pd.SparseDataFrame(
[['a',0,0,'b'],
[0,0,0,'c'],
[0,0,0,0],
[0,0,0,'a']],default_fill_value=0)
现在A.density
将按预期输出0.25
。
这是因为初始化程序无法推断列的dtypes。 引自pandas docs:
稀疏数据应与其密集表示具有相同的dtype。目前,支持float64,int64和bool dtypes。根据原始dtype,fill_value默认更改:
- float64:np.nan
- int64:0
- bool:False
但我们的SparseDataFrame的dtypes是:
A.dtypes
0 object
1 object
2 object
3 object
dtype: object
这就是为什么SparseDataFrame无法决定使用哪个填充值,因此使用了默认的np.nan
。
确定,现在我们有一个SparseDataFrame。让我们尝试替换其中的一些条目:
A.replace('a','z')
0 1 2 3
0 z 0 0 b
1 0 0 0 c
2 0 0 0 0
3 0 0 0 z
奇怪的是:
A.replace(0,np.nan)
0 1 2 3
0 a 0 0 b
1 0 0 0 c
2 0 0 0 0
3 0 0 0 a
你可以看到,这是不正确的!SparseDataFrame.replace()
仅适用于非填充值。
要更改填充值,您有以下选项:
DataFrame
,进行替换,然后转换回SparseDataFrame
。SparseDataFrame
,例如Wen's answer,或将default_fill_value
设置为新的填充值。当我在尝试最后一个选项时,发生了一些更奇怪的事情:
B = pd.SparseDataFrame(A,default_fill_value=np.nan)
B.density
0.25
B.default_fill_value
nan
到目前为止,这么好。但是......:
B
0 1 2 3
0 a 0 0 b
1 0 0 0 c
2 0 0 0 0
3 0 0 0 a
起初我真的很震惊。这甚至可能!? 继续,我试着看看列中发生了什么:
B[0]
0 a
1 0
2 0
3 0
Name: 0, dtype: object
BlockIndex
Block locations: array([0], dtype=int32)
Block lengths: array([1], dtype=int32)
列的dtype是object
,但与之关联的BlockIndex
的dtype是int32
,因此是奇怪的行为。
还有更多“奇怪”的事情发生,但我会在这里停下来
综上所述,我可以说你应该避免使用SparseDataFrame
,直到完全重写为止:)。
答案 1 :(得分:6)
这是我试过的
pd.SparseDataFrame(np.where(A==0, np.nan, A))
0 1 2 3
0 a NaN NaN b
1 NaN NaN NaN c
2 NaN NaN NaN NaN
3 NaN NaN NaN a