1
votes

créer n * n DataFrame à l'aide d'une fonction personnalisée

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


5 commentaires

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 et Zcef ? 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;)


3 Réponses :


-1
votes

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)

 entrez la description de l'image ici

du texte dessus: https://www.pythonforbeginners.com/ basics / list-comprehensions-in-python

espérons que cela vous aidera!


1 commentaires

il y a encore 2 boucles.



0
votes

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

Scott Boston 1ère solution

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

Scott Boston 2ème solution

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)

Solution vectorielle

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)


0 commentaires

3
votes

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


2 commentaires

En fait, je veux utiliser certaines fonctions personnalisées pour pouvoir remplacer cette fonction personnalisée


Merci pour votre temps et votre aide