You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何numpy.fill_diagonal()无法修改DataFrame的对角线值?

为什么numpy.fill_diagonal()无法修改DataFrame的对角线值?

我尝试用numpy.fill_diagonal()将DataFrame的对角线值修改为20000,但运行代码后对角线值仍为0。当前使用numpy版本2.1.0、pandas版本2.2.2,不需要提供for循环修改的方案,只想知道失败的原因。

复现代码

import numpy as np
import pandas as pd

nodes = ['A','B','C','D','E','F','G','H']
df_cap = pd.DataFrame(None, index=nodes, columns=nodes)

edges = {
    ('A', 'B'): 809, ('A', 'C'): 184, ('A', 'D'): 440, ('B', 'C'): 134, 
    ('B', 'E'): 277, ('B', 'F'): 138, ('C', 'D'): 194, ('C', 'F'): 144,
    ('C', 'G'): 139, ('D', 'E'): 190, ('D', 'G'): 284, ('E', 'F'): 100,
    ('E', 'H'): 281,('F', 'H'): 922,('G', 'F'): 123,('G', 'H'): 232
}

for i in nodes:
    for j in nodes:
        if (i,j) in edges:
            df_cap.loc[i,j] = edges[(i,j)]

nodes = nodes + ["Dummy"]


df_cap = df_cap.astype(float).fillna(0)
df_cap.loc["Dummy", :] = 0
df_cap.loc[:, "Dummy"] = 0
np.fill_diagonal(df_cap.values, 20000)

df_cap.loc["A", "Dummy"] = 20000
df_cap.loc["Dummy", "H"] = 20000
df_cap

问题原因

核心问题是添加Dummy行/列后,df_cap.values返回的是DataFrame底层数据的副本,而非引用:

  • 当执行df_cap.loc["Dummy", :] = 0和df_cap.loc[:, "Dummy"] = 0时,pandas需要扩展原DataFrame的维度,此时会重新分配内存空间,原有的连续数组被打散,df_cap.values不再指向DataFrame的底层内存,而是返回一个临时副本。
  • np.fill_diagonal()修改的是这个副本,修改完成后副本被丢弃,原DataFrame的数据完全没变化,所以对角线还是0。
  • 可以通过打印df_cap.values.flags.c_contiguous验证:添加Dummy后这个值会变成False,说明数组不是连续内存块,此时values返回的就是副本。

可行的修正方案(无需for循环)

方案1:确保操作连续数组

先将数组转换为连续内存块,再调用fill_diagonal:

# 替换原代码中的np.fill_diagonal行
arr = np.ascontiguousarray(df_cap.values)
np.fill_diagonal(arr, 20000)
df_cap[:] = arr

方案2:直接通过索引赋值

利用numpy的索引直接修改底层数据,不受内存连续性影响:

# 替换原代码中的np.fill_diagonal行
idx = np.arange(len(df_cap))
df_cap.values[idx, idx] = 20000

内容的提问来源于stack exchange,提问作者Joe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 12:33:33