2012-05-25 12 views
42

estoy usando un pandas DataFrame hacer una prueba t de modo de fila según este ejemplo:devolver varios valores de pandas aplicarse sobre una trama de datos

import numpy 
import pandas 

df = pandas.DataFrame(numpy.log2(numpy.randn(1000, 4), 
         columns=["a", "b", "c", "d"]) 

df = df.dropna() 

Ahora, suponiendo que tengo "a" y " b "como un grupo, y" c "y" d "en el otro, estoy realizando el t-test en hilera. Esto es bastante trivial con los pandas, usando apply con axis = 1. Sin embargo, puedo devolver un DataFrame de la misma forma si mi función no se agrega, o una serie si se agrega.

Normalmente me gustaría generar el valor p (por lo tanto, la agregación), pero me gustaría generar un valor adicional basado en otros cálculos (en otras palabras, devolver dos valores). Por supuesto, puedo hacer dos corridas, agregar los valores p primero, y luego hacer el otro trabajo, pero me preguntaba si existe una forma más eficiente de hacerlo ya que los datos son razonablemente grandes.

Como un ejemplo del cálculo, una función hypotethical sería:

from scipy.stats import ttest_ind 

def t_test_and_mean(series, first, second): 
    first_group = series[first] 
    second_group = series[second] 
    _, pvalue = ttest_ind(first_group, second_group) 

    mean_ratio = second_group.mean()/first_group.mean() 

    return (pvalue, mean_ratio) 

Entonces invoca con

df.apply(t_test_and_mean, first=["a", "b"], second=["c", "d"], axis=1) 

Por supuesto, en este caso se devuelve un solo serie con los dos tuplas como valor .

En su lugar, la salida esperada sería un DataFrame con dos columnas, una para el primer resultado y otra para el segundo. ¿Es esto posible o tengo que hacer dos carreras para los dos cálculos, luego combinarlos?

+3

¿Por qué está utilizando 'apply' en primer lugar? El resultado es un nuevo 'DataFrame' con una forma diferente a la entrada (tanto filas como columnas), por lo tanto, es un obj completamente nuevo. Simplemente podría hacer que 't_test_and_mean' acepte su marco de datos de entrada (y las columnas para agruparlo) y devolver un cuadro de datos de 1 fila-2-columnas, sin usar' apply'. – lbolla

+1

@lbolla Correcto, terminé haciendo eso en mi código, eventualmente. – Einar

Respuesta

59

La devolución de una serie, en lugar de una tupla, debe producir un nuevo DataFrame de múltiples columnas. Por ejemplo,

return pandas.Series({'pvalue': pvalue, 'mean_ratio': mean_ratio}) 
+0

Voy a volver a intentarlo el lunes, pero si recuerdo correctamente, intenta obligar a la estructura original de la columna (terminando con NA). – Einar

+0

@garrett - ¿Cómo puedo asegurarme de que el código devuelto de una función conservará su orden "prevista"? Mi caso de uso es: después de devolver esta serie de una función, la estoy guardando en un archivo csv usando df.to_csv. Además de por supuesto ser tontos, y nombrarlos como A, B, C, D para mantener su ordenamiento natural en el archivo csv. – ekta

+4

para especificar el orden de las columnas, intente construir las series con listas en lugar de dict, por ejemplo: 'pandas.Series ([pvalue, mean_ratio], index = ['pvalue', 'mean_ratio'])' – Garrett

Cuestiones relacionadas