2011-10-14 16 views
11

Tengo un código R que debo portar a python. Sin embargo, los datos y el marco mágico de R me impiden encontrar una buena forma de hacerlo en Python.Calcular dentro de las categorías: ¿Equivalente de ddply de R en Python?

de datos de ejemplo (R): cálculo

x <- data.frame(d=c(1,1,1,2,2,2),c=c(rep(c('a','b','c'),2)),v=1:6) 

muestra: salida

y <- ddply(x, 'd', transform, v2=(v-min(v))/(max(v)-min(v))) 

muestra:

d c v v2 
1 1 a 1 0.0 
2 1 b 2 0.5 
3 1 c 3 1.0 
4 2 a 4 0.0 
5 2 b 5 0.5 
6 2 c 6 1.0 

Así que aquí es mi pregunta para los Pythonistas por ahí: ¿Cómo ¿hacer lo mismo? Tienes una estructura de datos con un par de dimensiones importantes.

Para cada uno (c), y cada (d) cálculo (v-mín (v))/(máximo (v) -min (v))) y asócielo con el par correspondiente (d, c).

Siéntase libre de usar cualquier estructura de datos que desee, siempre y cuando sean rápidos en conjuntos de datos razonablemente grandes (los que caben en la memoria).

Respuesta

18

De hecho, pandas es la herramienta correcta (y solo, creo) para esto en Python. Es un poco menos mágico que plyr pero aquí es cómo hacer esto utilizando la funcionalidad GroupBy:

df = DataFrame({'d' : [1.,1.,1.,2.,2.,2.], 
       'c' : np.tile(['a','b','c'], 2), 
       'v' : np.arange(1., 7.)}) 
# in IPython 
In [34]: df 
Out[34]: 
    c d v 
0 a 1 1 
1 b 1 2 
2 c 1 3 
3 a 2 4 
4 b 2 5 
5 c 2 6 

Ahora escribe una pequeña función de transformación:

def f(group): 
    v = group['v'] 
    group['v2'] = (v - v.min())/(v.max() - v.min()) 
    return group 

Tenga en cuenta que esto también se encarga de AN ya que la variable v es un objeto pandas Series.

grupo ahora por la columna de d y aplicar f:

In [36]: df.groupby('d').apply(f) 
Out[36]: 
    c d v v2 
0 a 1 1 0 
1 b 1 2 0.5 
2 c 1 3 1 
3 a 2 4 0 
4 b 2 5 0.5 
5 c 2 6 1 
+0

Gracias por el minucioso ejemplo. – evanrsparks

4

Parece que quiere pandas y group by or aggregate.

+0

y otro adivinar: el método de "transformar grupos" aproximadamente 1/4 en la página de ese segundo enlace. –

1

También se puede lograr un mayor rendimiento si se utiliza numpy y scipy.

A pesar de un cierto código feo que será más rápido, forma pandas será lenta si el número de grupos es muy grande y puede ser incluso peor que R. Esto siempre será más rápido que R:

import numpy as np 
import numpy.lib.recfunctions 
from scipy import ndimage 

x = np.rec.fromarrays(([1,1,1,2,2,2],['a','b','c']*2,range(1, 7)), names='d,c,v') 

unique, groups = np.unique(x['d'], False, True) 
uniques = range(unique.size) 
mins = ndimage.minimum(x['v'], groups, uniques)[groups] 
maxs = ndimage.maximum(x['v'], groups, uniques)[groups] 

x2 = np.lib.recfunctions.append_fields(x, 'v2', (x['v'] - mins)/(maxs - mins + 0.0)) 

#save as csv 
np.savetxt('file.csv', x2, delimiter=';') 
Cuestiones relacionadas