【问题标题】:Fill the diagonal of Pandas DataFrame with elements from Pandas Series用 Pandas Series 中的元素填充 Pandas DataFrame 的对角线
【发布时间】:2019-01-02 08:41:39
【问题描述】:

给定一个带有索引的熊猫Series

import pandas as pd

s = pd.Series(data=[1,2,3],index=['a','b','c'])

如何使用 Series 填充 pandas 版本 >= 0.23.0 中空 DataFrame 的对角线条目?

生成的 DataFrame 如下所示:

  a b c
a 1 0 0
b 0 2 0
c 0 0 3

a prior similar question 将用相同的值填充对角线,我的问题是要求用系列中的不同值填充对角线。

提前感谢您的考虑和回复。

【问题讨论】:

    标签: python python-3.x pandas dataframe linear-algebra


    【解决方案1】:

    先创建DataFrame,再创建numpy.fill_diagonal

    import numpy as np
    
    s = pd.Series(data=[1,2,3],index=['a','b','c'])
    
    df = pd.DataFrame(0, index=s.index, columns=s.index, dtype=s.dtype)
    
    np.fill_diagonal(df.values, s)
    print (df)
       a  b  c
    a  1  0  0
    b  0  2  0
    c  0  0  3
    

    另一种解决方案是创建空的2d 数组,将值添加到对角线并最后使用DataFrame 构造函数:

    arr = np.zeros((len(s), len(s)), dtype=s.dtype)
    np.fill_diagonal(arr, s)
    
    print (arr)
    [[1 0 0]
     [0 2 0]
     [0 0 3]]
    
    df = pd.DataFrame(arr, index=s.index, columns=s.index)
    print (df)
       a  b  c
    a  1  0  0
    b  0  2  0
    c  0  0  3
    

    【讨论】:

      【解决方案2】:

      我不确定是否直接使用 Pandas 进行此操作,但如果您不介意使用 numpy.diag() 为您的系列构建对角线数据矩阵,然后将其插入 DataFrame,您可以轻松完成此操作:

      diag_data = np.diag(s)  # don't need s.as_matrix(), turns out
      df = pd.DataFrame(diag_data, index=s.index, columns=s.index)
      
         a  b  c
      a  1  0  0
      b  0  2  0
      c  0  0  3
      

      一行:

      df = pd.DataFrame(np.diag(s),
                        index=s.index,
                        columns=s.index)
      

      与由 10000 个元素组成的随机数组组成的系列的时序比较:

      s = pd.Series(np.random.rand(10000), index=np.arange(10000))
      
      df = pd.DataFrame(np.diag(s), ...)
      173 ms ± 2.91 ms per loop (mean ± std. dev. of 7 runs, 20 loops each)
      
      df = pd.DataFrame(0, ...)
      np.fill_diagonal(df.values, s)
      212 ms ± 909 µs per loop (mean ± std. dev. of 7 runs, 20 loops each)
      
      mat = np.zeros(...)
      np.fill_diagonal(mat, s)
      df = pd.DataFrame(mat, ...)
      175 ms ± 3.72 ms per loop (mean ± std. dev. of 7 runs, 20 loops each)
      

      这里显示的第一个和第三个选项看起来基本相同,而中间的选项最慢。

      【讨论】:

        猜你喜欢
        • 2016-09-15
        • 1970-01-01
        • 2019-04-26
        • 2018-01-22
        • 2014-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多