在 Python 中找到 Dataframe 子集的特征值

Find the eigenvalues of a subset of Dataframe in Python

我有一个 DataFrame 形式的矩阵

   df=     6M         1Y         2Y         4Y         5Y        10Y        30Y
      6M   n/a        n/a        n/a        n/a        n/a        n/a        n/a
      1Y   n/a          1  0.9465095   0.869504  0.8124711    0.64687  0.5089244
      2Y   n/a  0.9465095          1  0.9343177  0.8880676  0.7423546  0.6048189
      4Y   n/a   0.869504  0.9343177          1  0.9762842  0.8803984  0.7760753
      5Y   n/a  0.8124711  0.8880676  0.9762842          1  0.9117788  0.8404656
      10Y  n/a    0.64687  0.7423546  0.8803984  0.9117788          1  0.9514033
      30Y  n/a  0.5089244  0.6048189  0.7760753  0.8404656  0.9514033          1

我从矩阵(实数)中读取值,每当没有数据时我就插入 'n/a'(出于其他原因需要保持这种格式)。 我想计算包含浮点值的 DataFrame 子集的特征值(本质上是从 '1Y''30Y' 的子集)。

我可以使用 iloc

提取子集
tmp = df.iloc[1:df.shapep[0],1:df.shape[1]] 

这会提取正确的值(检查类型,它们是浮点数)。但是,当我尝试使用 np.linalg.eigvalsh 计算 tmp 的特征值时,出现错误

TypeError: No loop matching the specified signature and casting
was found for ufunc eigvalsh_lo

奇怪的是,当我从 'n/a''0.0' 替换的数据帧开始时,整个过程可以毫无问题地完成(它需要由 0.0 而不是例如 0)。 似乎如果数据帧的某些部分不是真实的,则子集提取不会将值转换为实数。

有没有办法克服这个问题?

IIUC 您可以使用 pd.to_numericand replace non-numeric with NaN then using fillna() 将您的列转换为数字 您可以使用 0 填充它们并使用 np.linalg.eigvals:

In [348]: df.apply(pd.to_numeric, errors='coerce')
Out[348]:
     6M        1Y        2Y        4Y        5Y       10Y       30Y
6M  NaN       NaN       NaN       NaN       NaN       NaN       NaN
1Y  NaN  1.000000  0.946509  0.869504  0.812471  0.646870  0.508924
2Y  NaN  0.946509  1.000000  0.934318  0.888068  0.742355  0.604819
4Y  NaN  0.869504  0.934318  1.000000  0.976284  0.880398  0.776075
5Y  NaN  0.812471  0.888068  0.976284  1.000000  0.911779  0.840466
10Y NaN  0.646870  0.742355  0.880398  0.911779  1.000000  0.951403
30Y NaN  0.508924  0.604819  0.776075  0.840466  0.951403  1.000000

In [350]: df.apply(pd.to_numeric, errors='coerce').fillna(0)
Out[350]:
     6M        1Y        2Y        4Y        5Y       10Y       30Y
6M    0  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000
1Y    0  1.000000  0.946509  0.869504  0.812471  0.646870  0.508924
2Y    0  0.946509  1.000000  0.934318  0.888068  0.742355  0.604819
4Y    0  0.869504  0.934318  1.000000  0.976284  0.880398  0.776075
5Y    0  0.812471  0.888068  0.976284  1.000000  0.911779  0.840466
10Y   0  0.646870  0.742355  0.880398  0.911779  1.000000  0.951403
30Y   0  0.508924  0.604819  0.776075  0.840466  0.951403  1.000000

In [351]: np.linalg.eigvals(df.apply(pd.to_numeric, errors='coerce').fillna(0))
Out[351]:
array([ 5.11329285,  0.7269089 ,  0.07770957,  0.01334893,  0.02909796,
        0.03964179,  0.        ])

应用 pd.to_numeric 后,所有值都变为浮点数:

In [352]: df.apply(pd.to_numeric, errors='coerce').dtypes
Out[352]:
6M     float64
1Y     float64
2Y     float64
4Y     float64
5Y     float64
10Y    float64
30Y    float64
dtype: object

注意 pd.to_numeric 仅适用于 pandas 版本 >= 0.17.0

如果您只有 'n/a' 个值,您可以使用 replaceastype(float):

df.replace('n/a', 0).astype(float)

In [364]: df.replace('n/a', 0).astype(float)
Out[364]:
     6M        1Y        2Y        4Y        5Y       10Y       30Y
6M    0  0.000000  0.000000  0.000000  0.000000  0.000000  0.000000
1Y    0  1.000000  0.946510  0.869504  0.812471  0.646870  0.508924
2Y    0  0.946510  1.000000  0.934318  0.888068  0.742355  0.604819
4Y    0  0.869504  0.934318  1.000000  0.976284  0.880398  0.776075
5Y    0  0.812471  0.888068  0.976284  1.000000  0.911779  0.840466
10Y   0  0.646870  0.742355  0.880398  0.911779  1.000000  0.951403
30Y   0  0.508924  0.604819  0.776075  0.840466  0.951403  1.000000

In [365]: np.linalg.eigvals(df.replace('n/a', 0).astype(float))
Out[365]:
array([ 5.11329285,  0.7269089 ,  0.07770957,  0.01334893,  0.02909796,
        0.03964179,  0.        ])