簡體   English   中英

從 pandas 數據框生成邊緣列表

[英]Generate an edge list from a pandas dataframe

假設我有一個這樣的熊貓數據框:

    Fruit_1   Fruit_2  Fruit_3 
0   Apple     Orange   Peach 
1   Apple     Lemon    Lime
2   Starfruit Apple    Orange 

可復制形式:

df = pd.DataFrame([['Apple', 'Orange', 'Peach'],
                   ['Apple', 'Lemon', 'Lime'],
                   ['Starfruit', 'Apple', 'Orange']],
                  columns=['Fruit_1', 'Fruit_2', 'Fruit_3'])

我想生成一個邊緣列表,其中包括:

Apple, Orange
Apple, Peach
Orange, Peach
Apple, Lemon
Apple, Lime
Lemon, Lime
Starfruit, Apple
Starfruit, Orange
Apple, Orange

我如何在 Python 中做到這一點?

我不知道熊貓,但你可以在行上使用itertools.combinations

itertools.combinations(row, 2)

這將創建一個迭代器,您可以簡單地將其轉換為對列表。

在將這些列表收集到列表后加入這些列表可以使用平面列表理解來完成

[pair for row in collected_rows for pair in row]

或者使用通常更快的numpy方式

data[:, np.c_[np.tril_indices(data.shape[1], -1)]]

如果你想要一個平面列表

data[:, np.c_[np.triu_indices(data.shape[1], 1)]].reshape(-1,2)

請注意, triu_indices按順序列出頂點,而tril_indices以相反的方式列出它們。 它們通常用於獲取矩陣的上三角形或下三角形的索引。

這是一個熊貓解決方案:

In [118]: from itertools import combinations

In [119]: df.apply(lambda x: list(combinations(x, 2)), 1).stack().reset_index(level=[0,1], drop=True).apply(', '.join)
Out[119]:
0        Apple, Orange
1         Apple, Peach
2        Orange, Peach
3         Apple, Lemon
4          Apple, Lime
5          Lemon, Lime
6     Starfruit, Apple
7    Starfruit, Orange
8        Apple, Orange
dtype: object

我寫這篇文章可能有點晚了,但最近我有必要完全按照你的要求去做。 我設法避免在這種情況下使用 itertools。 如果這是您的數據框:

df = pd.DataFrame([['Apple', 'Orange', 'Peach'],
               ['Apple', 'Lemon', 'Lime'],
               ['Starfruit', 'Apple', 'Orange']],
              columns=['Fruit_1', 'Fruit_2', 'Fruit_3'])

您只需調用一個函數:

>>> edgelist = get_edgelist(df)

      ID1        ID2
0   Apple     Orange
1   Apple      Peach
2  Orange      Peach
3   Apple      Lemon
4   Apple       Lime
5   Lemon       Lime
6   Apple     Orange
7   Apple  Starfruit
8  Orange  Starfruit

定義為:

def fast_combinations(row : list, self_loops = False) -> np.array:    
    
try:

        if self_loops:

            comb = np.unique(np.sort(np.array(np.meshgrid(row, row)).T.reshape(-1,2)), axis=0)

        else:
            
            comb = np.unique(np.sort(np.array(np.meshgrid(row, row)).T.reshape(-1,2)), axis=0)
            comb = np.delete(comb, np.where(comb[:,0] == comb[:,1]), axis=0)

        return comb

    except:

        return [[None, None]]


def get_edgelist(df, **kwargs):

    cols = df.columns
    df['combined'] = df[df.columns].values.tolist()

    # Clear space
    df.drop(cols, axis=1, inplace=True)

    arrays = []


    for row in range(len(df.index)):

        arrays.append(fast_combinations(df.loc[row, 'combined'], kwargs))

    return pd.DataFrame(np.concatenate( arrays, axis=0 ), columns=['ID1', 'ID2']).replace('nan', None).dropna().reset_index(drop=True)

我從函數中刪除了描述以使其更易於閱讀,但您可以在此處找到它們https://gist.github.com/Stefano314/607db3ffc53d680d60de61d09ca39a08

我在一個 250 萬行的數據幀上使用了它,從中我得到了 4500 萬個關聯,我在 i7-3770 上花了大約 48 分鍾。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM