使用numpy/pandas从两列创建联合命中数的矩阵

nah*_*var 2 python numpy distribution pandas

我有2个大型数据列(大约150万个值).它们的结构如下:

     col1 = [2,2,1,4,5,4,3,4,4,4,5,2,3,1,1 ..] etc.,
     col2 = [1,1,8,8,3,5,6,7,2,3,10.........] etc.,
Run Code Online (Sandbox Code Playgroud)

我想制作一个联合计数矩阵CountsMAT.col1的值范围为1到5,col2的范围为1到10.

     counts of [(1,2),(1,3),...(1,10),
                (2,1), (2,2),....(2,10),
                (3,1),......,(3,3)...(3,10),
                ...........................
                (5,1),(5,2),...(5,5).....(5,10)] are required ie.,

     a CountsMAT of size (5,10) 
     max(col1) = 5; max(col2) = 10 ;  
Run Code Online (Sandbox Code Playgroud)

我已经实现了一个带有defaultdict和for循环的版本,但这需要一段时间.我相信这可以直接用Pandas更好地处理,我很欣赏使用numpy/pandas的最佳实现.许多其他类似的查询指向Pandas的'groupby',但我并不精通它.

对于基于dict的实现,获取矩阵格式的输出也比较棘手.但是猜猜Pandas/numpy会更容易.谢谢!

wfl*_*nny 5

这可能有用(使用numpy.histogram2d):

import numpy as np

col1 = np.random.random_integers(1, 5, 100)
col2 = np.random.random_integers(1, 10, 100)
bin1 = np.arange(0.5, 6.5, 1)
bin2 = np.arange(0.5, 11.5, 1)

mat = np.histogram2d(col1, col2, bins=[bin1, bin2])[0]
print mat.shape
print mat
Run Code Online (Sandbox Code Playgroud)

产量

(5, 10)
array([[ 4.,  2.,  0.,  6.,  2.,  2.,  1.,  2.,  1.,  2.],
       [ 3.,  3.,  3.,  0.,  3.,  0.,  1.,  4.,  1.,  0.],
       [ 4.,  2.,  1.,  1.,  3.,  2.,  5.,  2.,  2.,  2.],
       [ 1.,  1.,  3.,  2.,  3.,  1.,  4.,  4.,  0.,  0.],
       [ 0.,  2.,  1.,  4.,  3.,  1.,  3.,  2.,  0.,  1.]])
Run Code Online (Sandbox Code Playgroud)

我没有使用长度超过几千的列表进行测试,但我认为它应该可以扩展几百万个值.


编辑:

嗨@nahsivar.我对大熊猫不太熟悉(但我可能应该这样),所以我花了几分钟时间玩耍.以下是获得所需内容的几种方法(我认为):

#instantiate dataframe
import pandas as pd
from random import choice
x_choice = 'ABCDE'
y_choice = 'ABCDEFGHIJ'
x, y = [], []
for i in range(100):
    x[i] = choice(x_choice)
    y[i] = choice(y_choice)

df = pd.DataFrame(data={'col1': x, 'col2': y})

# 1
df.pivot_table(rows='col1', cols='col2', aggfunc=len) 
# Use fill_value=0 to replace the NaNs with 0
# Output:
col2   A  B   C   D   E  F  G  H  I   J
col1                                   
A    NaN  1   3   1   2  2  2  1  4   2
B      1  1 NaN   3   5  1  2  3  1 NaN
C      4  1   2 NaN NaN  4  3  2  1   2
D      2  2   2   1   1  3  3  4  4   2
E      1  1   1 NaN   4  2  6  3  2   2

# 2
df.groupby('col2')['col1'].value_counts().unstack(level=0)
# Output:
col2   A  B   C   D   E  F  G  H  I   J
A    NaN  1   3   1   2  2  2  1  4   2
B      1  1 NaN   3   5  1  2  3  1 NaN
C      4  1   2 NaN NaN  4  3  2  1   2
D      2  2   2   1   1  3  3  4  4   2
E      1  1   1 NaN   4  2  6  3  2   2

# 3
pd.crosstab(df.col1, df.col2)
# Output:
col2  A  B  C  D  E  F  G  H  I  J
col1                              
A     0  1  3  1  2  2  2  1  4  2
B     1  1  0  3  5  1  2  3  1  0
C     4  1  2  0  0  4  3  2  1  2
D     2  2  2  1  1  3  3  4  4  2
E     1  1  1  0  4  2  6  3  2  2
Run Code Online (Sandbox Code Playgroud)