J'ai une colonne comme celle-ci ci-dessous:
Data A Av Zcef A 1 2 4 Av 2 4 8 Zcef 4 8 16
Je veux une sortie avec l'utilisation d'une fonction comme
def len_mul(a,b): return len(a) * len(b)
Cette fonction peut être replace,
Data 0 A 1 Av 2 Zcef
Je peux le faire en utilisant la boucle for, mais je ne veux pas utiliser la boucle for.
J'essaie d'utiliser pd.crosstab
, mais je suis bloqué à aggfunc
.
len_mul strong > la fonction est importante car c'est un exemple de fonction pour plus de simplicité.
3 Réponses :
Ma suggestion serait de construire le tableau avec une compréhension de liste au lieu d'une boucle.
De cette façon, vous pouvez facilement créer un dataframe avec par la suite.
Exemple d'utilisation:
import pandas as pd array = ['A','B','C'] def function (X): return X**2 L = [[function(X) for X in pd.np.arange(3)] for Y in pd.np.arange(3)] L >>> [[0, 1, 4], [0, 1, 4], [0, 1, 4]] pd.DataFrame(L, columns=array, index=array)
du texte dessus: https://www.pythonforbeginners.com/ basics / list-comprehensions-in-python
espérons que cela vous aidera!
il y a encore 2 boucles.
Prenons ceci comme un commentaire élaboré. Je pense que cela dépend principalement de votre fonction len_mul
. Si vous voulez faire exactement la même chose que dans votre question, vous pouvez utiliser un peu d'algèbre linéaire. En particulier le fait que multipliez une matrice nxq par une matrice qxm vous obtenez une matrice nxm.
%%time v = df["Data"].str.len().values arr = df["Data"].values m = v.reshape((-1,1)).dot(v.reshape((1,-1))) df_out3 = pd.DataFrame(m, columns=arr, index=arr) CPU times: user 477 ms, sys: 188 ms, total: 666 ms Wall time: 666 ms
Mise à jour
Je suis d'accord que Scott Boston La solution est bonne pour le cas général d'une fonction personnalisée. Mais je pense que vous devriez chercher un moyen possible de traduire votre fonction en quelque chose que vous pourriez faire en utilisant l'algèbre linéaire.
Voici un certain timing:
%%time lens = df['Data'].str.len() arr = df['Data'].values df_out2 = pd.DataFrame(np.outer(lens,lens), index=arr, columns=arr) CPU times: user 99.7 ms, sys: 232 ms, total: 332 ms Wall time: 331 ms
%%time idx = pd.MultiIndex.from_product([df['Data'], df['Data']]) df_out1 = pd.Series(idx.map(lambda x: len_mul(*x)), idx).unstack() CPU times: user 1min 32s, sys: 10.3 s, total: 1min 43s Wall time: 1min 43s
import pandas as pd import numpy as np import string alph = list(string.ascii_letters) n = 10000 data = ["".join(np.random.choice(alph, np.random.randint(1,10))) for i in range(n)] data = sorted(list(set(data))) df = pd.DataFrame({"Data":data}) def len_mul(a,b): return len(a) * len(b)
import pandas as pd import numpy as np df = pd.DataFrame({"Data":["A", "Av", "Zcef"]}) # this is the len of every entries v = df["Data"].str.len().values # this reshape as a (3,1) matrix v.reshape((-1,1)) # this reshape as a (1,3) matrix v.reshape((1,-1)) # arr = df["Data"].values # this is the matrix multiplication m = v.reshape((-1,1)).dot(v.reshape((1,-1))) # your expected output df_out = pd.DataFrame(m, columns=arr, index=arr)
Utilisation de votre fonction personnalisée:
Data A Av Zcef Data A 1 2 4 Av 2 4 8 Zcef 4 8 16
Résultat:
lens = df['Data'].str.len() pd.DataFrame(np.outer(lens,lens), index = df['Data'], columns=df['Data'])
Cela provenait de @piRSquared SO Post
Vous pouvez utiliser np.outer
avec le constructeur pd.DataFrame:
A Av Zcef A 1 2 4 Av 2 4 8 Zcef 4 8 16
Sortie :
def len_mul(a,b): return len(a) * len(b) idx = pd.MultiIndex.from_product([df['Data'], df['Data']]) df_out = pd.Series(idx.map(lambda x: len_mul(*x)), idx).unstack() df_out
En fait, je veux utiliser certaines fonctions personnalisées pour pouvoir remplacer cette fonction personnalisée
Merci pour votre temps et votre aide
Voulez-vous nous montrer votre boucle afin que nous puissions mieux comprendre la logique que vous utilisez? Utilisez-vous le nom len ()? Pourquoi avez-vous
Zce
etZcef
? D'où vient le dernier?désolé erreur de frappe .. je l'ai corrigé
Veuillez jeter un œil au calendrier dans ma réponse mise à jour.
@ user32185 Merci pour vos mises à jour, je voulais quelque chose où je puisse remplacer la fonction len_mul par ma vraie fonction.
J'ai compris. Je voulais juste souligner le fait que les solutions vectorielles sont plus rapides;)