基于对称矩阵的Pandas序列重复项的消除

2024-04-18 22:07:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我对熊猫还不熟悉,一直无法找到一个简洁的解决方法来解决以下问题。在

假设我有一系列基于对称(距离)矩阵的数据,从下面的序列中删除重复项的最有效方法是什么?在

from pandas import DataFrame
df = DataFrame([[0, 1, 2],
                [1, 0, 3],
                [2, 3, 0]], 
               index=['a', 'b', 'c'], 
               columns=['a', 'b', 'c'])
ser = df.stack()
ser

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

我要做的是删除重复对,因为矩阵是对称的。输出应该如下所示

^{pr2}$

Tags: columns数据方法fromimport距离dataframepandas
2条回答

我不知道这有多有效,但这是有效的:

seen = []

for tup in ser.index.tolist():
    if tup[::-1] in seen:
        continue
    seen.append(tup)

ser_reduced = ser[seen]

ser_reduced
Out[9]: 
a  a    0
   b    1
   c    2
b  b    0
   c    3
c  c    0
dtype: int64

以下代码比当前接受的答案运行得更快:

import numpy as np

def dm_to_series1(df):
    df = df.astype(float)
    df.values[np.triu_indices_from(df, k=1)] = np.nan
    return df.unstack().dropna()

DataFrame的类型被转换为float,这样元素可以用np.nan为null。在实践中,距离矩阵可能已经存储了浮动,所以这一步可能不是严格必要的。上三角(不包括对角线)为空,在将DataFrame转换为Series之后,这些条目将被删除。在

为了比较运行时,我修改了当前接受的解决方案。请注意,我将其更新为使用集合而不是列表以加快运行速度:

^{pr2}$

在原始示例数据集上测试两个解决方案:

import pandas as pd

df = pd.DataFrame([[0, 1, 2],
                   [1, 0, 3],
                   [2, 3, 0]], 
                  index=['a', 'b', 'c'], 
                  columns=['a', 'b', 'c'])

我的解决方案:

In [4]: %timeit dm_to_series1(df)
1000 loops, best of 3: 538 µs per loop

@马吕斯的解决方案:

In [5]: %timeit dm_to_series2(df)
1000 loops, best of 3: 816 µs per loop

我还通过使用scikit bio的skbio.stats.distance.randdm函数随机生成一个50x50矩阵并将其转换为DataFrame来测试较大距离的矩阵:

from skbio.stats.distance import randdm
big_dm = randdm(50)
big_df = pd.DataFrame(big_dm.data, index=big_dm.ids, columns=big_dm.ids)

我的解决方案:

In [7]: %timeit dm_to_series1(big_df)
1000 loops, best of 3: 649 µs per loop

@马吕斯的解决方案:

In [8]: %timeit dm_to_series2(big_df)
100 loops, best of 3: 3.61 ms per loop

请注意,我的解决方案可能不如@Marius的解决方案节省内存,因为我要创建输入DataFrame的副本并对其进行修改。如果修改输入DataFrame是可以接受的,那么可以通过使用就地DataFrame操作来更新代码以提高内存效率。在

注意:我的解决方案是受this SO question中的答案启发的。在

相关问题 更多 >