如何从两个稀疏格式的数据帧生成 coo 矩阵

问题描述 投票:0回答:1

我有两个稀疏格式的数据帧,索引和列略有不同。我需要两个数据帧的串联数据帧的 coo 版本。当我尝试从它们生成 coo 矩阵时,我在

data
属性中得到零,这对我来说是意想不到的。即使所有列都有
pd.SparseDtype("float",0)
数据类型。看来 fillna(0) 方法引入了一些零,这些零渗透到稀疏格式的数据中......不应该包含零。

这里有一些代码来重现该行为

    import pandas as pd

    A = pd.DataFrame(np.eye(3),index=['a','b','c'],
    columns=['a','b','c']).astype(pd.SparseDtype("float",0))
    
    B = pd.DataFrame(np.random.normal(size=(2,2)),
                 index=['d','e'],
                 columns=['a','b'],
                 ).astype(pd.SparseDtype("float",0))

    c = pd.concat([A,B],axis=0).fillna(0)

在该示例中,

c.sparse.to_coo().data
或只是
c.c.sparse.sp_values
都包含零,这违背了使用稀疏数据格式的目的。我不明白发生了什么事。如何以稀疏格式连接数据帧而不占用这些空间?我正在使用 pandas 版本 2.2.2

python pandas scipy
1个回答
0
投票

您的数据框和 coo 版本:

In [253]: A
Out[253]: 
     a    b    c
a  1.0  0.0  0.0
b  0.0  1.0  0.0
c  0.0  0.0  1.0

In [254]: print(A.sparse.to_coo())
  (0, 0)    1.0
  (1, 1)    1.0
  (2, 2)    1.0

In [255]: B
Out[255]: 
          a         b
d  1.300532  0.507797
e  2.716205  0.350493

In [256]: print(B.sparse.to_coo())
  (0, 0)    1.3005317919570971
  (1, 0)    2.716205281906014
  (0, 1)    0.5077973046544041
  (1, 1)    0.3504927594184647

以及串联版本:

In [257]: c
Out[257]: 
          a         b    c
a  1.000000  0.000000  0.0
b  0.000000  1.000000  0.0
c  0.000000  0.000000  1.0
d  1.300532  0.507797  0.0
e  2.716205  0.350493  0.0

In [258]: print(c.sparse.to_coo())
  (0, 0)    1.0
  (3, 0)    1.3005317919570971
  (4, 0)    2.716205281906014
  (1, 1)    1.0
  (3, 1)    0.5077973046544041
  (4, 1)    0.3504927594184647
  (2, 2)    1.0
  (3, 2)    0.0
  (4, 2)    0.0

所以 (3,2) 和 (4,2) 来自

fillna
。如果您使用不同的填充,效果会更明显。

稀疏矩阵确实有一种删除多余零的方法。那不是自动的。而且我不太了解 pandas 稀疏代码,无法将其传递回数据框。

In [259]: M=c.sparse.to_coo()
In [260]: M.eliminate_zeros(); print(M)
  (0, 0)    1.0
  (3, 0)    1.3005317919570971
  (4, 0)    2.716205281906014
  (1, 1)    1.0
  (3, 1)    0.5077973046544041
  (4, 1)    0.3504927594184647
  (2, 2)    1.0

In [261]: M.A
Out[261]: 
array([[1.        , 0.        , 0.        ],
       [0.        , 1.        , 0.        ],
       [0.        , 0.        , 1.        ],
       [1.30053179, 0.5077973 , 0.        ],
       [2.71620528, 0.35049276, 0.        ]])

使用其他 fillna 值:

In [262]: pd.concat([A,B],axis=0).fillna(np.nan)
Out[262]: 
          a         b    c
a  1.000000  0.000000  0.0
b  0.000000  1.000000  0.0
c  0.000000  0.000000  1.0
d  1.300532  0.507797  NaN
e  2.716205  0.350493  NaN

Pandas 稀疏代码在某种程度上是实验性的,因此像

concat
这样的步骤错过这样的细节也就不足为奇了。显然没有任何代码来检查
fillna
值是否与稀疏填充相同,并进行此类清理。

© www.soinside.com 2019 - 2024. All rights reserved.