TL;DR
Je vais résumer l'histoire de l'utilisation de apply () lors du prétraitement des données avec Pandas.
http://pandas.pydata.org/pandas-docs/stable/ pandas est une bibliothèque qui fournit les méthodes nécessaires à l'analyse des données en Python. Il peut gérer un large éventail de données, des séries chronologiques aux séries de données telles que les tableaux, et peut être agrégé à grande vitesse. Dans le monde d'aujourd'hui, vous entendez souvent le cas de "l'analyse des données avec Python".
Lors de l'exécution de travaux d'analyse de données dans Moff, nous traitons souvent les données après avoir extrait les données préliminaires, puis les analyser sur place. Après avoir dessiné la table de données que vous souhaitez créer à la fin, vous devrez exécuter un pré-traitement d'ici là.
Par exemple, supposons que vous ayez le jeu de données suivant.
Après cela, supposons que vous souhaitiez prétraiter "Je veux ajouter un nouveau nombre de caractères dans le nom à la colonne".
À cette époque, il était particulièrement observé chez les stagiaires qui commençaient tout juste la programmation, mais le code de prétraitement suivant était souvent vu dans le prétraitement.
data['len'] = 0
for k, d in data['name'].iteritems():
data['len'][k] = len(d)
Certes, cela suffit pour le résultat de sortie, et je pense que quelques lignes de données prendront certainement autant de temps.
Maintenant, traitons-le avec apply (). apply () est l'une des méthodes fournies dans les types DataFrame et Series. Dans les expressions DataFrame et Series, chaque valeur du DataFrame groupé est utilisée comme argument et la valeur de retour de la fonction donnée à l'argument de apply () est utilisée. Il peut renvoyer des valeurs Series, DataFrame ou scalaires.
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.apply.html https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.apply.html
Dans l'exemple précédent, si vous créez une fonction qui renvoie len, elle ressemblera à ceci.
def return_len(x)
return len(x)
data['len'] = data['name'].apply(return_len)
Si vous connaissez l'expression lambda (fonction anonyme), vous pouvez également effectuer les opérations suivantes.
data['len'] = data['name'].apply(lambda x: len(x))
Je pense que ce sera relativement simple en termes de description.
Comme vous l'avez peut-être remarqué, cette fois j'ai introduit une fonction qui renvoie le résultat de len () en implémentant la fonction. Si vous y réfléchissez bien, len () lui-même est aussi une fonction, vous pouvez donc le faire comme ceci.
data['len'] = data['name'].apply(len)
S'il s'agit d'un processus simple, il peut être possible de le résoudre avec une boucle for, mais lorsque vous envisagez un prétraitement plus compliqué, il est préférable d'en faire une fonction et de l'appliquer avec apply () plutôt que ce qui précède, et de remarquer les erreurs, etc. Je pense que ce sera moins cher.
Dans l'exemple ci-dessus, étant donné que la quantité de données est petite, je pense qu'il y a une différence dans la vitesse de traitement, je vais donc montrer le résultat de l'application du traitement qui génère la longueur des données de chaîne de caractères aléatoires. L'environnement de vérification est le suivant.
# of data | for loop | pandas.DataFrame.apply() |
---|---|---|
100 | 3.907sec | 0.079sec |
10000 | 415.032sec | 0.231sec |
100000 | 3100.906sec | 1.283sec |
Comme vous pouvez le voir, même avec environ 100 cas, il y a une différence d'environ 3,8 secondes, et lorsque le nombre de cas est de 10 000 ou 100 000, la différence de temps nécessaire pour produire le résultat devient énorme. Il est clair qu'il est préférable d'utiliser apply () pour obtenir un résultat rapide, quelle que soit la taille de l'ensemble de données ou le prétraitement.
Par exemple, voici le corps principal de Apply of DataFrame https://github.com/pandas-dev/pandas/blob/5a7b5c958c6f004c395136f9438a1ed6c04861dd/pandas/core/frame.py#L6440
Si vous suivez frame_apply ()
https://github.com/pandas-dev/pandas/blob/5a7b5c958c6f004c395136f9438a1ed6c04861dd/pandas/core/apply.py#L26
Il semble que quelque chose soit écrit dans une classe appelée FrameApply.
https://github.com/pandas-dev/pandas/blob/5a7b5c958c6f004c395136f9438a1ed6c04861dd/pandas/core/apply.py#L56
Puisque nous appelons get_result () sur frame_apply (), nous allons suivre le processus.
https://github.com/pandas-dev/pandas/blob/5a7b5c958c6f004c395136f9438a1ed6c04861dd/pandas/core/apply.py#L144
Il existe une branche en fonction du paramètre, mais il semble que ce qui suit est appelé à moins qu'un argument optionnel ne soit donné.
https://github.com/pandas-dev/pandas/blob/5a7b5c958c6f004c395136f9438a1ed6c04861dd/pandas/core/apply.py#L269
Il semble que libreduction.compute_reduction () effectue le calcul dans apply_standard (). Après cela, il semble que apply_series_generator () et wrap_results () produisent des résultats.
Il semble que la libreduction soit dans / _lib / reduction.pyx
.
https://github.com/pandas-dev/pandas/blob/master/pandas/_libs/reduction.pyx
Apparemment, cela semble se comporter comme diviser les données de la matrice avec numpy.ndarray.shape dans Reducer, et faire diverses choses à partir de for i in range (self.n results):
.
https://github.com/pandas-dev/pandas/blob/5a7b5c958c6f004c395136f9438a1ed6c04861dd/pandas/_libs/reduction.pyx#L88
De là, cela semble être une histoire sur Numpy. Même si vous parcourez le code ci-dessus, Pandas
Dans ce qui précède, il semble qu'aucun point ne soit défini dans le calcul, il semble donc que le traitement soit conçu sur Numpy. Car, à la fin, il y a res = self.f (chunk)
sur le réducteur ci-dessus, et le point qu'il est spécialement conçu dans le processus de calcul après le processus d'application de la fonction au ndarray de Numpy. Je n'ai pas pu le trouver. Il y avait une description selon laquelle il était traité séparément dans Chunk, mais les détails du traitement réel n'étaient pas clairs au moment de res = self.f (chunk)
de l'application de la fonction, et du traitement du côté Numpy par la suite Il semble être complété par. Dans la mesure où cela est dit dans les rues, il est logique d'ajouter que le processus de calcul dans Numpy est plus rapide que le processus de calcul en Python pur seul.
J'aimerais en savoir un peu plus, mais comme il est volumineux d'écrire plus, je profiterai d'une autre occasion pour spécifier le traitement dans Numpy. Quoi qu'il en soit, il a été décidé que ce n'était pas du moins sur Pandas. (Bien qu'il ne soit toujours pas clair si cela dépend des performances du langage ou s'il est conçu par un traitement de calcul)
Sous la forme d'un dérivé de apply (), il existe respectivement map () et applymap () dans Series et DataFrame. À première vue, je me demandais ce qui était différent, alors j'ai fait une recherche rapide et j'ai trouvé que les différences étaient résumées dans la réponse StackOverFlow ci-dessous. https://stackoverflow.com/a/56300992/7649377
Si vous ne supprimez que les points principaux,
Est-ce là le point?
La prochaine fois que j'écrirai un article avec cette histoire, je lirai Numpy et l'attraperai. Merci beaucoup.
Recommended Posts