在pandas.DataFrame的对角线上设置值

Tim*_*Tim 24 python numpy pandas

我有一个pandas数据帧我想将对角线设为0

import numpy
import pandas

df = pandas.DataFrame(numpy.random.rand(5,5))
df

Out[6]:
     0           1           2           3               4
0    0.536596    0.674319    0.032815    0.908086    0.215334
1    0.735022    0.954506    0.889162    0.711610    0.415118
2    0.119985    0.979056    0.901891    0.687829    0.947549
3    0.186921    0.899178    0.296294    0.521104    0.638924
4    0.354053    0.060022    0.275224    0.635054    0.075738
5 rows × 5 columns
Run Code Online (Sandbox Code Playgroud)

现在我想将对角线设置为0:

for i in range(len(df.index)):
    for j in range(len(df.columns)):
        if i==j:
            df.loc[i,j] = 0
df
Out[9]:
     0           1           2           3           4
0    0.000000    0.674319    0.032815    0.908086    0.215334
1    0.735022    0.000000    0.889162    0.711610    0.415118
2    0.119985    0.979056    0.000000    0.687829    0.947549
3    0.186921    0.899178    0.296294    0.000000    0.638924
4    0.354053    0.060022    0.275224    0.635054    0.000000
5 rows × 5 columns
Run Code Online (Sandbox Code Playgroud)

但必须有更多的pythonic方式!?

unu*_*tbu 46

In [21]: df.values[[np.arange(df.shape[0])]*2] = 0

In [22]: df
Out[22]: 
          0         1         2         3         4
0  0.000000  0.931374  0.604412  0.863842  0.280339
1  0.531528  0.000000  0.641094  0.204686  0.997020
2  0.137725  0.037867  0.000000  0.983432  0.458053
3  0.594542  0.943542  0.826738  0.000000  0.753240
4  0.357736  0.689262  0.014773  0.446046  0.000000
Run Code Online (Sandbox Code Playgroud)

请注意,这仅df在与列具有相同行数时才有效.另一种适用于任意形状的方法是使用np.fill_diagonal:

In [36]: np.fill_diagonal(df.values, 0)
Run Code Online (Sandbox Code Playgroud)

  • @PhilippSchwarz关于np.fill_diagonal的一件好事是它可以在您可以放入RAM的任何DataFrame或矩阵上工作,而无需使用更多的内存。“填充”分配有效地在内存中“就地”发生,并使DataFrame的“索引”和“列”以及其他属性保持不变。 (2认同)

And*_*ouw 10

使用np.fill_diagonal(df.values, 1)是最简单的,但是您需要确保您的列都具有相同的数据类型,我混合了 np.float64 和 python 浮点数,它只会影响 numpy 值。要修复你必须将所有内容转换为 numpy。


Phi*_*arz 5

该解决方案是矢量化的,速度非常快,与其他建议的解决方案不同,它适用于 df 矩阵的任何列名称和大小。

\n
def pd_fill_diagonal(df_matrix, value=0): \n    mat = df_matrix.values\n    n = mat.shape[0]\n    mat[range(n), range(n)] = value\n    return pd.DataFrame(mat)\n
Run Code Online (Sandbox Code Playgroud)\n

507 列和行的 Dataframe 上的性能

\n
% timeit pd_fill_diagonal(df, 0)\n
Run Code Online (Sandbox Code Playgroud)\n

1000 个循环,3 个循环中最好的:每个循环 145 \xc2\xb5s

\n