【问题标题】:Eigenvalues from pandas rows来自熊猫行的特征值
【发布时间】:2019-11-08 11:29:18
【问题描述】:

我有一个pandasDataFrame,其中的行代表一个对称矩阵分量。

                            sxx         syy             szz         sxy         syz         sxz                                                                                           
    NodeID      time
    1500000     20921.0     2504729.0   -16524560.0     -3966213.0  5058878.0   8026349.0   390275.7
                20923.0     2541577.0   -16459500.0     -3930280.0  5047995.0   8019404.0   393201.3
                20925.0     2582004.0   -16384690.0     -3891037.0  5035703.0   8011226.0   396850.2
                20927.0     2618859.0   -16313310.0     -3855520.0  5024095.0   8003384.0   400578.7
                20933.0     2703961.0   -16133460.0     -3773937.0  4995101.0   7985394.0   411183.2

矩阵将如下所示。

[[sxx, sxy, sxz],
 [sxy, syy, syz],
 [sxz, syz, szz]]

从每一行计算特征值的最快方法是什么?

我尝试在每一行上“应用”np.linalg.eigvalsh。但是,当我有接近一百万行时,这需要相当长的时间。

编辑

为了给出完整的上下文,我还应该提到这个DataFrame 是对象定义的一部分。 object.dfDataFrame。下面是相关代码。

    def s1(self):
        """Returns the first principal stress for every node every timepoint"""
        return self.df.apply(principal, axis=1, label="s1")

def principal(s, label):
    principals = np.linalg.eigvalsh(
        np.array(
            [s.sxx, s.sxy, s.sxz, s.sxy, s.syy, s.syz, s.sxz, s.syz, s.szz]
        ).reshape(3, 3)
    )
    if label.lower() == "s3":
        return principals[0]
    elif label.lower() == "s2":
        return principals[1]
    elif label.lower() == "s1":
        return principals[2]
    else:
        raise ValueError("Invalid Input, choose from s1, s2, or s3.")

【问题讨论】:

  • 你如何将它应用到每一行?贴出代码?您是否首先将行重塑为对称方阵?
  • 实际上这个数据框是对象定义的一部分。我将发布相关信息作为问题的一部分。
  • @DrBwts,是的。数据框中的每一行实际上是对称矩阵的上半部分。
  • 您可以取消 .reshape(3,3) 并将矩阵定义为 np.array([[s.sxx, s.sxy, s.sxz], [s.sxy, s.syy, s.syz], [s.sxz, s.syz, s.szz]]) 以开始

标签: python pandas numpy linear-algebra eigenvalue


【解决方案1】:

您可以设置列的顺序以生成视图,然后使用.values 将其传递给数组(比np.array(..) 快),然后将eigvalsh 应用于(n, 3, 3) 数组:

values = df[['sxx', 'sxy', 'sxz', 'sxy', 'syy', 'syz', 'sxz', 'syz', 'szz']].values.reshape(-1,3))
eigh = eigvalsh(values.reshape((-1, 3, 3)))
eigh

>>array([[-21253030.07083309,  -1397298.11167328,   4664284.18250638],
       [-21184732.23304478,  -1361435.36228467,   4697964.59532944],
       [-21106512.77176102,  -1322433.70013306,   4735223.47189408],
       [-21032246.72681734,  -1287171.41922922,   4769447.14604654],
       [-20847979.70886149,  -1205613.19093403,   4850156.89979552]])

【讨论】:

  • 这是一个更快的方法!但是,我丢失了索引数据。我想我可以使用与数据帧相同的索引从 numpy 数组重新创建 pd.Series
  • 没错。您应该以第一个维度与数据框长度相同且顺序相同的数组结尾。您在数组中没有索引,但您始终可以使用 iloc 访问原始数据框,或者只是将列附加回来
猜你喜欢
  • 1970-01-01
  • 2016-03-12
  • 2018-09-27
  • 2019-02-16
  • 2017-06-24
  • 2020-08-24
  • 1970-01-01
  • 1970-01-01
  • 2018-08-08
相关资源
最近更新 更多