熊猫传播DF到指标DF

时间:2018-10-15 11:28:59

标签: python pandas

我有一个这样的数据框

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 :(得分:3)

11125max一起使用:

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

另一种解决方案-按组创建列表,然后使用get_dummies

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

答案 1 :(得分:1)

编辑:使用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