Pandas Spread DF на индикатор DF - PullRequest
       1

Pandas Spread DF на индикатор DF

0 голосов
/ 15 октября 2018

У меня есть такой фрейм данных

import pandas as pd

test = pd.DataFrame(data={"IDX": [0,0,0,1,1,2], 
                          "VAL": [27,5,13,27,24,13]})

   IDX  VAL
0    0   27
1    0    5
2    0   13
3    1   27
4    1   24
5    2   13

И я хочу распространить его так, чтобы IDX стал столбцами, VAL стал именами строк, а фактические значения были просто индикаторами того, отсутствует или нет значение,вот так:

out = pd.DataFrame(data={"0": [1, 1, 0, 1],
                         "1": [0, 0, 1, 1],
                         "2": [0, 1, 0, 0]}, index=[5, 13, 24, 27])

    0  1  2
5   1  0  0
13  1  0  1
24  0  1  0
27  1  1  0

Есть ли способ сделать это эффективно без циклов for?

Ответы [ 2 ]

0 голосов
/ 15 октября 2018

РЕДАКТИРОВАТЬ: Используйте get_dummies.Смотрите ответ @ Jezrael.Исправлено мое использование crosstabs ниже.

pd.crosstab добьется цели (если мы сделаем небольшую модификацию)

pd.crosstab(index=test['VAL'], columns=test['IDX'])

IDX  0  1  2
VAL         
5    1  0  0
13   1  0  1
24   0  1  0
27   1  1  0

С crosstab считает значения и не создает индикаторы, такие как get_dummies, если бы мы хотели использовать crosstabs, нам бы пришлось выбрать все значения выше 0 и присвоить их 1.

In [76]: test = pd.DataFrame(data={"IDX": [0,0,0,0,0,1,1,2], 
    ...:                           "VAL": [27,27,27,5,13,27,24,13]})
    ...:                           
    ...:                           
    ...:                           

In [77]: pd.crosstab(index=test['VAL'], columns=test['IDX'])
Out[77]: 
IDX  0  1  2
VAL         
5    1  0  0
13   1  0  1
24   0  1  0
27   3  1  0 <----------- IDX 0 VAL 27 = 3

In [78]: cross_tab = _

In [79]: cross_tab[cross_tab > 0] = 1

In [80]: cross_tab
Out[80]: 
IDX  0  1  2
VAL         
5    1  0  0
13   1  0  1
24   0  1  0
27   1  1  0 <---------- Back to a 1
0 голосов
/ 15 октября 2018

Используйте get_dummies с max:

df = pd.get_dummies(test.set_index('VAL')['IDX'].sort_index()).max(level=0)
print (df)
     0  1  2
VAL         
5    1  0  0
13   1  0  1
24   0  1  0
27   1  1  0

Другое решение - создайте списки по группам, а затем используйте MultiLabelBinarizer:

s = test.groupby('VAL')['IDX'].apply(list)
print (s)
VAL
5        [0]
13    [0, 2]
24       [1]
27    [0, 1]
Name: IDX, dtype: object

from sklearn.preprocessing import MultiLabelBinarizer

mlb = MultiLabelBinarizer()
df = pd.DataFrame(mlb.fit_transform(s),columns=mlb.classes_, index=s.index)
print (df)
     0  1  2
VAL         
5    1  0  0
13   1  0  1
24   0  1  0
27   1  1  0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...