web-dev-qa-db-fra.com

Renvoyer plusieurs valeurs de pandas appliquer sur un DataFrame

J'utilise un Pandas DataFrame pour faire un test t par ligne selon cet exemple:

import numpy
import pandas

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

df = df.dropna()

Maintenant, en supposant que j'ai "a" et "b" dans un groupe, et "c" et "d" dans l'autre, j'effectue le test t en ligne. C'est assez banal avec les pandas, en utilisant apply avec axis = 1. Cependant, je peux soit renvoyer un DataFrame de la même forme si ma fonction ne s'agrège pas, ou un Series s'il s'agrège.

Normalement, je produisais simplement la valeur de p (donc, l'agrégation) mais je voudrais générer une valeur supplémentaire basée sur d'autres calculs (en d'autres termes, retourner deux valeurs). Je peux bien sûr faire deux exécutions, en agrégeant d'abord les valeurs de p, puis en faisant l'autre travail, mais je me demandais s'il y avait un moyen plus efficace de le faire car les données sont raisonnablement grandes.

À titre d'exemple de calcul, une fonction hypotéthique serait:

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)

Puis invoqué avec

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

Bien sûr, dans ce cas, il renvoie une seule série avec les deux tuples comme valeur.

Au lieu de cela, la sortie attendue serait un DataFrame avec deux colonnes, une pour le premier résultat et une pour la seconde. Est-ce possible ou je dois faire deux exécutions pour les deux calculs, puis les fusionner ensemble?

45
Einar

Le renvoi d'une série, plutôt que d'un tuple, devrait produire un nouveau DataFrame à plusieurs colonnes. Par exemple,

return pandas.Series({'pvalue': pvalue, 'mean_ratio': mean_ratio})
72
Garrett