我的意思是这样的:
我有DataFrame
列,可能是分类或名义。对于每个观察(行),我想生成一个新行,其中变量的每个可能值现在都是它自己的二进制变量。例如,此矩阵(第一行是列标签)
'a' 'b' 'c'
one 0.2 0
two 0.4 1
two 0.9 0
three 0.1 2
one 0.0 4
two 0.2 5
会被转换成这样的东西:
'a' 'b' 'c'
one two three [0.0,0.2) [0.2,0.4) [0.4,0.6) [0.6,0.8) [0.8,1.0] 0 1 2 3 4 5
1 0 0 0 1 0 0 0 1 0 0 0 0 0
0 1 0 0 0 0 0 1 0 1 0 0 0 0
0 1 0 0 0 0 0 1 1 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0 1 0 0 0
1 0 0 1 0 0 0 0 0 0 0 0 1 0
0 1 0 0 1 0 0 0 0 0 0 0 0 1
初始矩阵中的每个变量(列)都被分成所有可能的值。如果它是分类的,那么每个可能的值将成为新列。如果它是一个浮点数,则值会以某种方式进行分箱(例如,总是分成10个分档)。如果它是一个int,那么它可以是每个possibel int值,或者也可能是binning。
仅供参考:在我的实际应用中,该表最多有200万行,完整的“扩展”矩阵可能有数百列。
有没有简单的方法来执行此操作?
另外,我也愿意跳过这一步,因为我真的想要计算一个Burt表(它是交叉表的对称矩阵)。是否有一种简单的方法可以使用crosstab
函数执行类似的操作?否则,计算交叉列表只是一个简单的矩阵乘法。
答案 0 :(得分:31)
请注意,我已实施新的cut
和qcut
功能,以便对连续数据进行离散化处理:
http://pandas-docs.github.io/pandas-docs-travis/basics.html#discretization-and-quantiling
答案 1 :(得分:5)
对于标示列,例如示例中的a
和c
列,您可以使用pandas内置方法get_dummies()。
例:
import pandas as pd
s1 = ['a', 'b', np.nan]
pd.get_dummies(s1)
a b
0 1 0
1 0 1
2 0 0
答案 2 :(得分:4)
你可以使用某种广播:
In [58]: df
Out[58]:
a b c
0 one 0.2 0
1 two 0.4 1
2 two 0.9 0
3 three 0.1 2
4 one 0.0 4
5 two 0.2 5
In [41]: (df.a.values[:,numpy.newaxis] == df.a.unique()).astype(int)
Out[41]:
array([[1, 0, 0],
[0, 1, 0],
[0, 1, 0],
[0, 0, 1],
[1, 0, 0],
[0, 1, 0]])
In [54]: ((0 <= df.b.values[:,numpy.newaxis]) & (df.b.values[:,numpy.newaxis] < 0.2)).astype(int)
Out[54]:
array([[0],
[0],
[0],
[1],
[1],
[0]])
In [59]: (df.c.values[:,numpy.newaxis] == df.c.unique()).astype(int)
Out[59]:
array([[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[1, 0, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0],
[0, 0, 0, 0, 1]])
然后将所有作品与pandas.concat
或类似作品一起加入。
答案 3 :(得分:3)
我怀疑你会打败patsy的简单性。它的设计正是为了完成这项任务:
>>> from patsy import dmatrix
>>> dmatrix('C(a) + C(b) + C(c) - 1', df, return_type='dataframe')
C(a)[one] C(a)[three] C(a)[two] C(b)[T.0.1] C(b)[T.0.2] C(b)[T.0.4] C(b)[T.0.9] C(c)[T.1] C(c)[T.2] C(c)[T.4] C(c)[T.5]
0 1 0 0 0 1 0 0 0 0 0 0
1 0 0 1 0 0 1 0 1 0 0 0
2 0 0 1 0 0 0 1 0 0 0 0
3 0 1 0 1 0 0 0 0 1 0 0
4 1 0 0 0 0 0 0 0 0 1 0
5 0 0 1 0 1 0 0 0 0 0 1
此处C(a)
表示将变量转换为分类,而-1
则是为了避免输出拦截列。
答案 4 :(得分:1)
将一些其他评论汇总到一个回答OP问题的回复中。
d = {'a' : pd.Series(['one', 'two', 'two', 'three', 'one', 'two']),
'b' : pd.Series([0.2, 0.4, 0.9, 0.1, 0.0, 0.2]),
'c' : pd.Series([0, 1, 0, 2, 4, 5]) }
data = pd.DataFrame(d)
a_cols = pd.crosstab(data.index, [data.a])
b_bins = pd.cut(data.b, [0.0, 0.2, 0.4, 0.6, 0.8, 1.0], right=False)
b_cols = pd.crosstab(data.index, b_bins)
c_cols = pd.crosstab(data.index, [data.c], )
new_data = a_cols.join(b_cols).join(c_cols)
new_data.index.names = ['']
print new_data.to_string()
"""
one three two [0, 0.2) [0.2, 0.4) [0.4, 0.6) [0.8, 1) 0 1 2 4 5
0 1 0 0 0 1 0 0 1 0 0 0 0
1 0 0 1 0 0 1 0 0 1 0 0 0
2 0 0 1 0 0 0 1 1 0 0 0 0
3 0 1 0 1 0 0 0 0 0 1 0 0
4 1 0 0 1 0 0 0 0 0 0 1 0
5 0 0 1 0 1 0 0 0 0 0 0 1
"""