2012-05-29 24 views
7

Quiero decir algo como esto:¿Cómo discretizo los valores en un DataFrame de pandas y los convierto en una matriz binaria?

Tengo un DataFrame con columnas que pueden ser categóricas o nominales. Para cada observación (fila), quiero generar una nueva fila donde cada valor posible para las variables ahora es su propia variable binaria. Por ejemplo, esta matriz (primera fila es etiquetas de columna)

'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 

sería convertido en algo como esto:

'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 

Cada variable (columna) en la matriz inicial conseguir agrupadas en todos los valores posibles . Si es categórico, cada valor posible se convierte en una nueva columna. Si se trata de un flotante, los valores se agrupan de alguna manera (por ejemplo, siempre se dividen en 10 bandejas). Si es un int, entonces puede ser cualquier valor int posible, o tal vez también binning.

FYI: en mi aplicación real, la tabla tiene hasta 2 millones de filas, y la matriz completa "expandida" puede tener cientos de columnas.

¿Hay una manera fácil de realizar esta operación?

Por separado, también estaría dispuesto a omitir este paso, ya que estoy tratando de calcular una tabla Burt (que es una matriz simétrica de las tabulaciones cruzadas). ¿Hay alguna manera fácil de hacer algo similar con la función crosstab? De lo contrario, calcular la tabulación cruzada es solo una simple multiplicación de matrices.

Respuesta

4

Usted puede utilizar algún tipo de radiodifusión:

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]]) 

Y luego unir todas las piezas juntas con pandas.concat o similar.

+0

¿Hay una manera de realizar algo similar por un uso inteligente de '' crosstab' o pivot_table' o 'stack' o algo similar? –

+0

Claro, para 'a' y 'c' es fácil: 'pandas.concat ([pandas.crosstab (df.index, [df.a]), pandas.crosstab (df.index, [df.c])] , eje = 1) '.Para 'b', supongo que se puede hacer especificando un 'aggfunc' apropiado en' crosstab' ... – lbolla

1

La elaboración de un par de otros comentarios en una sola contestación respuesta PO preguntas.

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 
""" 
3

Dudo que vencer a la simplicidad patsy 's. Fue diseñado precisamente para esta tarea:

>>> 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 

Aquí los medios C(a) convertir la variable categórica y a la -1 es evitar la emisión de una columna de intercepción.

5

Para columnas etiquetadas como la columna a y c en su ejemplo, puede utilizar el método de creación de pandas get_dummies().

Ej .:

import pandas as pd 
s1 = ['a', 'b', np.nan] 
pd.get_dummies(s1) 
     a b 
    0 1 0 
    1 0 1 
    2 0 0 
+0

¡Whoa! Esto es genial. –

Cuestiones relacionadas