我有一个这样的数据框
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循环的情况下有效地做到这一点?
答案 0 :(得分:3)
将11125与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
另一种解决方案-按组创建列表,然后使用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