Search code examples
pythonpandasscikit-learndummy-variableone-hot-encoding

How to create dummy variable and then aggregate using scikit-learn?


I know it can be easily realized using the package pandas, but because it is too sparse and large (170,000 x 5000), and at the end I need to use sklearn to deal with the data again, I'm wondering if there is a way to do with sklearn. I tried the one hot encoder, but got stuck to associate dummies with the 'id'.

df = pd.DataFrame({'id': [1, 1, 2, 2, 3, 3], 'item': ['a', 'a', 'c', 'b', 'a', 'b']})

   id item
0   1    a
1   1    a
2   2    c
3   2    b
4   3    a
5   3    b

dummy = pd.get_dummies(df, prefix='item', columns=['item'])
dummy.groupby('id').sum().reset_index()

   id  item_a  item_b  item_c
0   1       2       0       0
1   2       0       1       1
2   3       1       1       0

Update:

Now I'm here, and the 'id' is lost, how to do aggregation then?

lab = sklearn.preprocessing.LabelEncoder()
labels = lab.fit_transform(np.array(df.item))
enc = sklearn.preprocessing.OneHotEncoder()
dummy = enc.fit_transform(labels.reshape(-1,1))

dummy.todense()

matrix([[ 1.,  0.,  0.],
        [ 1.,  0.,  0.],
        [ 0.,  0.,  1.],
        [ 0.,  1.,  0.],
        [ 1.,  0.,  0.],
        [ 0.,  1.,  0.]])

Solution

  • In case anyone needs a reference in the future, I put my solution here. I used scipy sparse matrix.

    First, do a grouping and count the number of records.

    df = df.groupby(['id','item']).size().reset_index().rename(columns={0:'count'})
    

    This takes some time but not days.

    Then use pivot table, which I found a solution here.

    from scipy.sparse import csr_matrix
    
    def to_sparse_pivot(df, id, item, count):
        id_u = list(df[id].unique())
        item_u = list(np.sort(df[item].unique()))
        data = df[count].tolist()
        row = df[id].astype('category', categories=id_u).cat.codes
        col = df[item].astype('category', categories=item_u).cat.codes
        return csr_matrix((data, (row, col)), shape=(len(id_u), len(item_u)))
    

    Then call the function

    result = to_sparse_pivot(df, 'id', 'item', 'count')