Показать все совпадающие пары в одном фрейме данных - Python Record Linkage - PullRequest
0 голосов
/ 24 января 2019

У меня есть объект MultiIndex для панд:

In [0]: index
Out[0]: 
MultiIndex(levels=[[1, 2, 3, 8], [10, 11]],
       labels=[[0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 0, 1, 0, 1, 0, 1]])

Этот объект MultiIndex определяет следующие 8 пар: (1,10), (1,11), (2,10), (2,11), (3,10), (3,11), (8,10), (8,11).

Элементы, перечисленные в уровнях, соответствуют индексу DataFrame:

In [1]: df
Out[1]: 
     col_1   col_2
0        0       1
1        2       3
2        4       5
3        6       7
4        8       9
5       10      11
6       12      13
7       14      15
8       16      17
9       18      19
10      20      21
11      22      23

Я хотел бы создать новый DataFrame, который показывает все пары, определенные выше. Нечто похожее:

In [2]: result
Out[2]: 
    col_1   col_2     pair
        2       3        0
       20      21        0
        2       3        1
       22      23        1
        4       5        2
       20      21        2
        4       5        3
       22      23        3
        6       7        4
       20      21        4
        6       7        5
       22      23        5
       16      17        6
       20      21        6
       16      17        7
       22      23        7

Есть ли эффективный способ реализовать это? (если возможно, без петель)

Заранее спасибо

Ответы [ 3 ]

0 голосов
/ 24 января 2019

pd.concat

Не обязательно самый эффективный ... но умный (-:

pd.concat(
    [df.loc[[*pair]].assign(pair=i) for i, pair in enumerate(index)]
).reset_index(drop=True)

    col_1  col_2  pair
0       2      3     0
1      20     21     0
2       2      3     1
3      22     23     1
4       4      5     2
5      20     21     2
6       4      5     3
7      22     23     3
8       6      7     4
9      20     21     4
10      6      7     5
11     22     23     5
12     16     17     6
13     20     21     6
14     16     17     7
15     22     23     7

zip

аналогично указанному выше

i_s, j_s = zip(*[(i, j) for j, p in enumerate(index) for i in p])
df.loc[[*i_s]].assign(pair=j_s).reset_index(drop=True)


    col_1  col_2  pair
0       2      3     0
1      20     21     0
2       2      3     1
3      22     23     1
4       4      5     2
5      20     21     2
6       4      5     3
7      22     23     3
8       6      7     4
9      20     21     4
10      6      7     5
11     22     23     5
12     16     17     6
13     20     21     6
14     16     17     7
15     22     23     7
0 голосов
/ 24 января 2019

Использование stack с iloc или reindex

df.iloc[m.to_frame().stack()].assign(key=m.to_frame().reset_index(drop=True).stack().index.get_level_values(0))
Out[205]: 
    col_1  col_2  key
1       2      3    0
10     20     21    0
1       2      3    1
11     22     23    1
2       4      5    2
10     20     21    2
2       4      5    3
11     22     23    3
3       6      7    4
10     20     21    4
3       6      7    5
11     22     23    5
8      16     17    6
10     20     21    6
8      16     17    7
11     22     23    7
0 голосов
/ 24 января 2019

Настройка

m = pd.MultiIndex(levels=[[1, 2, 3, 8], [10, 11]],
       labels=[[0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 0, 1, 0, 1, 0, 1]])

Вы можете работать с базовым numpy массивом

a = np.stack(m.values)
v = df.values
res = v[a]
c = res.shape[-1]

u = pd.DataFrame(res.reshape(-1, df.shape[1]), columns=df.columns)
u['pair'] = np.repeat(np.arange(u.shape[0] // c), c)

    col_1  col_2  pair
0       2      3     0
1      20     21     0
2       2      3     1
3      22     23     1
4       4      5     2
5      20     21     2
6       4      5     3
7      22     23     3
8       6      7     4
9      20     21     4
10      6      7     5
11     22     23     5
12     16     17     6
13     20     21     6
14     16     17     7
15     22     23     7

Пояснение

Когда мы индексируем значения DataFrame, используя все комбинации MultiIndex, мы не только получаем правильные отображения, мы собираем сгруппированные строки вместе в измерении вывода. Мы можем использовать форму из этого, чтобы вывести столбец pair позже.

print(v[a])

array([[[ 2,  3],
        [20, 21]],

       [[ 2,  3],
        [22, 23]],

       [[ 4,  5],
        [20, 21]],

       [[ 4,  5],
        [22, 23]],

       [[ 6,  7],
        [20, 21]],

       [[ 6,  7],
        [22, 23]],

       [[16, 17],
        [20, 21]],

       [[16, 17],
        [22, 23]]], dtype=int64)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...