[PYTHON] Parlez des fonctionnalités dont les pandas et moi étions en charge dans le projet

introduction

Cette fois, en 6 semaines, j'ai participé à un projet allant du team building à la sortie du produit. Veuillez consulter le lien ci-dessous pour l'ensemble du projet. J'aimerais que vous lisiez les articles et les articles passés sur moi, mais bref, je suis inexpérimenté et je recherche un ingénieur.

Cliquez ici pour le projet

Dans cet article, je vais sortir ce que j'ai appris en implémentant les fonctions dont j'étais en charge.

À propos des pandas

Un type de module python. Si vous mettez cela, vous pourrez utiliser diverses fonctions liées à l'analyse et à l'analyse des données. Pour plus d'informations, voir Documents officiels et Cet article. ..

Ce n'est que lorsque la production a été décidée lors du premier MTG que j'ai décidé d'utiliser des pandas, mais comme j'étais nouveau dans les pandas, je leur ai demandé d'utiliser l'une des six semaines du projet comme pré-apprentissage, donc c'est basique. Apprenez la cible Après cela, je l'ai utilisé en le fabriquant et en le vérifiant. Cependant, je n'ai pas pu l'utiliser sérieusement, principalement

C'est la partie fondamentale. Regardons chacun d'eux.

Qu'est-ce qu'un fichier CSV en premier lieu?

→ L'histoire rapide est le format utilisé pour les logiciels de calcul de tableaux avec des lignes et des colonnes telles que EXCEL et des feuilles de calcul. Vous pouvez utiliser des pandas pour le lire et le traiter et convertir les types de données python dans ce format. À propos, le type DataFrame est ce que les pandas ont converti pour que le CSV puisse être géré par python.

#Prix Quantité de vente Taux de stock
#Pomme 300 10 80%
#Mikan 100 2 20%
#Melon 900 6 60%

Si vous affichez le DataFrame avec print () etc., il sera affiché dans le formulaire ci-dessus, par exemple. Vous avez vu ce tableau.

Lire le fichier CSV

Touchons réellement les pandas. Tout d'abord, lisez le fichier CSV. Au fait, qu'est-ce qu'un fichier csv?


client_id,client_name
1,Échantillon B Co., Ltd.
2,Échantillon I Co., Ltd.
3,Échantillon F Co., Ltd.
4,Échantillon D Co., Ltd.
5,Échantillon E Co., Ltd.
6,Échantillon C Co., Ltd.
7,Échantillon G Co., Ltd.
8,Échantillon A Co., Ltd.
9,Échantillon H Co., Ltd.

Ce sera un fichier comme celui-ci. Définissez les noms de champ sur la première ligne, séparés par des virgules. Vous pouvez voir que la deuxième ligne et les suivantes représentent les données qui seront insérées dans le champ. Pour le lire réellement, écrivez comme suit.

python


import glob
import pandas as pd

sample_data = pd.read_csv('sample.csv')

#S'il y a plusieurs
df = pd.DataFrame() #Créer une instance vide
file_list = glob.glob(CSV_PATH) #Spécifiez le chemin du fichier. En utilisant le module glob`sample/data*`Si vous définissez un argument tel que, tous les fichiers csv contenant la chaîne de caractères "data" sous ce répertoire seront ciblés.


for file_count in file_list:
    dfn = pd.read_csv(file_count)
    df = pd.concat([df, dfn])

La méthode read_csv () est une méthode pour lire CSV, plus précisément une méthode pour convertir un fichier CSV en type DataFrame. L'argument est le chemin du fichier. Rappelez-vous que pandas importe essentiellement avec ʻimport pandas as pd` et l'utilise sous la forme d'une méthode pd. Et la chose importante est que si vous souhaitez lire plusieurs fichiers CSV en même temps, par exemple, vous pouvez combiner plusieurs fichiers CSV un par un dans un fichier comme décrit ci-dessus. C'est pourquoi nous faisons cela. Que fais tu

  1. Créez une instance vide
  2. Spécifiez le chemin du fichier du répertoire contenant le fichier CSV dans la variable
  3. Combinez-les dans l'ordre avec une instruction for

Cela signifie que. Comme concat () est une méthode utilisée pour combiner des fichiers CSV, vous pouvez voir que CSV est combiné les uns après les autres avec des instances DataFrame vides dans un CSV. Spécifiez une liste comme argument. Le chemin du fichier est entré dans file_list, mais comme sample / data * est spécifié, le fichier avec le nom de fichier contenant la chaîne de caractères data sous sample sera saisi à plusieurs reprises dans l'ordre croissant. Par exemple


sample
  |
  |-----data1.csv
  |-----data2.csv
  |-----data3.csv

Dans un tel cas, il sera traité dans l'ordre à partir de data1.csv. Puisque concat () ne peut pas être combiné à la fois, c'est un processus comme celui-ci. À propos, il existe également une méthode appelée merge () pour la fusion, mais elle semble être utilisée pour fusionner des fichiers qui ont la même clé primaire mais des colonnes différentes.

Essayez de faire du fichier CSV un type de dictionnaire python

Ensuite, rendons le CSV lu modifiable avec python.


import pandas as pd

CSV_COLUMN = ['date','sales','client_id','staff_id']

#Définir une liste vide
data = []
field_names = CSV_COLUMN
#Lisez le fichier sans écrire.
with open(file_path, 'r', encoding='utf-8') as f:
    #Obtenez chaque champ dans le type de dictionnaire et ajoutez-le aux données ligne par ligne
    for row in csv.DictReader(f, fieldnames=field_names):
        data.append(row)


Le nom de champ défini est affecté à CSV_COLUMN. Ensuite, utilisez with open () as f: pour lire le fichier CSV en lecture seule. Cette syntaxe n'est pas limitée au CSV, c'est une syntaxe utilisée lors de la lecture d'un fichier, et la précédente consistait à le convertir en type DataFrame, mais cette fois il obtiendra simplement le contenu du fichier. L'argument contient le chemin du fichier, les options et les paramètres de codage, et le contenu lu est affecté à la variable f. Cette fois, comme mentionné ci-dessus, il est lu en lecture seule au format utf-8. Ensuite, cette fois, le contenu du fichier lu est extrait avec une instruction for. csv.DictReader () est une méthode pour obtenir un fichier CSV sous forme de dictionnaire. Un exemple de traitement est le suivant.

#Si vous lisez un tel fichier CSV

date,sales,client_id,staff_id
2020-01-01,8390,8,9
2020-01-02,8712,1,8
2020-01-03,8146,6,8

#Il sera stocké dans des données comme celle-ci

[([('date', '2020-01-01'), ('sales', '8390'), ('client_id', '8'), ('staff_id', '9')]),
([('date', '2020-01-02'), ('sales', '8712'), ('client_id', '1'), ('staff_id', '8')]),
([('date', '2020-01-03'), ('sales', '8146'), ('client_id', '6'), ('staff_id', '8')])]


Essayez de modifier les données du type de dictionnaire

Ajoutons un champ aux données précédentes.

#La première ligne est traitée comme un nom de champ, donc là`tax_salse`Ajoutez un champ appelé
data[0]['tax_sales'] = 'tax_sales'

#Ensuite, la deuxième ligne et les suivantes(=La valeur réelle de chaque champ)Entrez la valeur dans le champ nouvellement ajouté avec l'instruction for.
for row in data[1:]:
    #taxe de ligne de ligne_Insérez la valeur obtenue en multipliant le champ ventes par le taux de taxe dans le champ vente.
    row['tax_sales'] = int(row['sales']) * (1.0 + TAX_RATE)

Essayez de combiner différents fichiers CSV avec fusion et sortie CSV

import pandas as pd

CSV_COLUMN_ADD = ['date','sales','tax_sales','client_id', 'client_name','staff_id','staff_name']

#Convertissez les données de chaque type de dictionnaire en type DataFrame.
sales_data = pd.DataFrame(sales_data)
client_data = pd.DataFrame(client_data)
staff_data = pd.DataFrame(staff_data)

#fusionner
merge1 = pd.merge(sales_data, client_data, how='outer')
merge2 = pd.merge(merge1, staff_data, how='outer')
#Argument CSV_COLUMN_Trier les champs dans l'ordre ADD
merge_data_result = merge2.loc[:,CSV_COLUMN_ADD]
#Supprimer l'index
merge_data_result = merge_data_result.drop(merge_data_result.index[0])


Comme concat (), merge () spécifie également deux fichiers que vous souhaitez combiner avec l'argument. comment est une option pour spécifier comment rejoindre. how = 'external' regarde la clédans la spécification de jointure externe et se joint pour que toutes les données qui ne sont que dans une table soient laissées. En outre, lorsque merge () est effectué, le nom du champ est ajouté en tant qu'index sur la deuxième ligne et il peut être dupliqué avec la ligne 0, donc cette fois il est supprimé avec la méthode drop (). Vous pouvez faire référence au nom de la colonne avec ʻarray name.loc [], et en appliquant ceci, cette fois, en définissant:, CSV_COLUMN_ADD, toutes les colonnes sont triées dans l'ordre de CSV_COLUMN_ADD. ..

C'est l'utilisation très basique des pandas et python.

Version avancée

Voyons maintenant comment utiliser Django tout en interagissant réellement avec la base de données. Par exemple, si vous disposez du modèle suivant et que vous souhaitez effectuer ce type de traitement en conséquence.

<détails>

Modèle qui stocke les informations de marque (modèle de fonds commun de placement) </ summary>


from django.db import models
from accounts.models import CustomUser


class MutualFund(models.Model):
    class Meta:
        db_table = 'MutualFund'
        verbose_name_plural = 'Informations sur les fiducies d'investissement'

    DELETE_FLAG = ((0, 'Non supprimé'), (1, 'Effacer'))

    # id = AutoField(primary_key=True)  #Aucune définition requise car elle est ajoutée automatiquement
    url = models.CharField('URL du fonds', max_length=255, null=True, blank=True)
    fund_name = models.CharField(
        'Nom du fonds', max_length=255, null=True, blank=True)
    company = models.CharField('Nom de la compagnie', max_length=255, null=True, blank=True)
    category_obj = models.ForeignKey(
        Category,
        verbose_name='Catégorie',
        on_delete=models.CASCADE
    )
    rate = models.IntegerField('Note globale', null=True, blank=True)
    return_percent = models.FloatField('Taux de retour(3 années)', null=True, blank=True)
    risk = models.FloatField('Valeur du risque(3 années)', null=True, blank=True)
    fee = models.FloatField('Frais de fiducie, etc. (taxes incluses)', null=True, blank=True)
    net_assets = models.IntegerField('Actif net (millions de yens)', null=True, blank=True)
    delete_flag = models.IntegerField('Supprimer le drapeau', choices=DELETE_FLAG, default=0)

    def __str__(self):
        return self.fund_name

<détails>

Modèle faisant référence aux informations des modèles associés (modèle Portfolio) </ summary>


from django.db import models
import sys
import pathlib
# base.Récupère le chemin absolu du répertoire où se trouve py
# current_dir = pathlib.Path(__file__).resolve().parent
# #Ajouter un chemin avec le module
# sys.path.append( str(current_dir) + '/../' )

# print(sys.path)
from accounts.models import CustomUser
from fund.models import MutualFund


#Les informations sont référencées à partir de chaque modèle.
# customuser_obj et mutuel_fund_obj contient des informations sur les référents.

class Portfolio(models.Model):
    customuser_obj = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
    mutual_fund_obj = models.ForeignKey(MutualFund, on_delete=models.CASCADE)
    amount = models.IntegerField(null=True, blank=True)

<détails>

Code de traitement </ summary>



# risk_col et retour_Définition provisoire de col
risk_col = 0
return_col = 0

#Fonction pour trouver la différence de risque


def risk_differ(x):
    return risk_col - x.loc["risk"]


#Fonction pour trouver la différence de retour


def return_differ(x):
    return return_col - x.loc["return_percent"]


def find_fund_near_risk(fund_id, num_fund_obj):
    """
Convertir l'enregistrement acquis en DataFrame, créer un nouveau champ, stocker la différence de risque avec la marque spécifiée en tant que valeur absolue, la trier et la renvoyer

    Arguments:
        fund_id : str
nom commercial.
        num_fund_obj : int
Nombre d'acquisitions.

    Returns:
        brand_risk_near : DataFrame
    """
    #Obtenez des enregistrements de type dictionnaire.
    brand_info = MutualFund.objects.values(
        "id", "company", "fund_name", "risk")

    #Convertir en DataFrame
    brand_info_df = pd.DataFrame(brand_info)

    #Extraire les champs de risque des stocks désignés de DF
    find_obj = brand_info_df[brand_info_df["id"] == fund_id]
    risk_col = find_obj["risk"]

    #Créez un champ pour saisir le résultat du calcul de la différence de risque
    brand_info_df["differ"] = np.nan

    #Stockez la valeur de la différence de risque dans le champ de différence et rendez la valeur absolue.
    brand_info_df["differ"] = brand_info_df.apply(risk_differ, axis=1).abs()

    #Supprimer la ligne d'informations de la marque spécifiée par l'argument
    deleterow = brand_info_df.index[brand_info_df["id"] == fund_id]
    brand_info_df = brand_info_df.drop(deleterow)

    #Trier par ordre croissant et supprimer les champs de différence et d'identifiant
    brand_info_df = brand_info_df.sort_values("differ")
    brand_info_df = brand_info_df.drop(columns=["id", "differ"])

    #Limite de nombre
    brand_risk_near = brand_info_df.head(num_fund_obj)

    return brand_risk_near

Cependant, il est difficile à comprendre du coup, alors voyons d'abord comment faire fonctionner DB dans Django. Pour plus de détails et des spécifications plus complexes, veuillez vous référer au document ou à l'article de référence car il a été organisé de manière simple à comprendre. Je vais jeter un bref coup d'œil ici.

Avoir

Il existe deux modèles d'acquisition: l'acquisition de tous les cas et l'acquisition par recherche. Dans tous les cas, models.objects.all () obtiendra tous les enregistrements de ce modèle. Ensuite, il y a le modèle à rechercher et à obtenir, mais vous utiliserez la méthode get () ou la méthode filter (), mais en gros, vous les utiliserez correctement car les valeurs de retour sont différentes. get () retourne un seul enregistrement qui correspond à l'argument en tant que ** objet **. Ainsi, par exemple, models.objects.get (pk = 1) est utilisé lorsque vous souhaitez obtenir uniquement des données spécifiques. En revanche, filter () renvoie les enregistrements correspondants sous forme de ** liste d'objets **. Donc, en gros, il est utilisé lors de la récupération d'enregistrements qui devraient être enregistrés plusieurs fois, tels que models.objects.filter (name = 'sample'). Par ailleurs, bien entendu, puisque la valeur de retour est une liste d'objets, elle ne peut pas être traitée telle quelle, donc la méthode values () décrite plus loin sera utilisée. Si vous voulez faire quelque chose comme get () avec filter (), suivez filter () avec la méthode first (). first () renvoie le premier des ensembles de requêtes récupérés en tant qu'objet.

Convertir l'enregistrement récupéré

Vous pouvez souhaiter que certains des enregistrements acquis soient de type dictionnaire ou liste. Dans ce cas, utilisez la méthode values () et sa méthode dérivée values_list ().

Par exemple, utilisez-le comme suit.


#Extraire les enregistrements du modèle où la valeur du champ de nom est échantillon
query = models.objects.filter(name='sample')

#Obtenez la valeur du champ id dans une liste à partir des enregistrements extraits
models_column_id_list = query.values_list('id')

#Obtenez les enregistrements de champ d'ID, de nom et d'e-mail directement à partir du modèle dans une liste de dictionnaires
models_column_dict_list = models.objects.values("id", "name", "email")


Illustration

Revenons maintenant au code du début. Cette fois, j'ai défini la différence de risque ou de rendement entre les actions en valeur absolue et je les trie par ordre croissant. J'ai implémenté une fonction pour énumérer les actions dont le risque (rendement) est similaire au stock spécifié, mais c'est le code ci-dessous au début.


from fund.models import MutualFund
from portfolio.models import Portfolio
import pandas as pd
import numpy as np
from django.db.models import Count


# risk_col et retour_Définition provisoire de col
risk_col = 0
return_col = 0

#Fonction pour trouver la différence de risque


def risk_differ(x):
    return risk_col - x.loc["risk"]


#Fonction pour trouver la différence de retour


def return_differ(x):
    return return_col - x.loc["return_percent"]


def find_fund_near_risk(fund_id, num_fund_obj):
    """
Convertir l'enregistrement acquis en DataFrame, créer un nouveau champ, stocker la différence de risque avec la marque spécifiée en tant que valeur absolue, la trier et la renvoyer

    Arguments:
        fund_id : str
nom commercial.
        num_fund_obj : int
Nombre d'acquisitions.

    Returns:
        brand_risk_near : DataFrame
    """
    #Obtenez des enregistrements de type dictionnaire.
    brand_info = MutualFund.objects.values(
        "id", "company", "fund_name", "risk")

    #Convertir en DataFrame
    brand_info_df = pd.DataFrame(brand_info)

    #Extraire les champs de risque des stocks désignés de DF
    find_obj = brand_info_df[brand_info_df["id"] == fund_id]
    risk_col = find_obj["risk"]

    #Créez un champ pour saisir le résultat du calcul de la différence de risque
    brand_info_df["differ"] = np.nan

    #Stockez la valeur de la différence de risque dans le champ de différence et rendez la valeur absolue.
    brand_info_df["differ"] = brand_info_df.apply(risk_differ, axis=1).abs()

    #Supprimer la ligne d'informations de la marque spécifiée par l'argument
    deleterow = brand_info_df.index[brand_info_df["id"] == fund_id]
    brand_info_df = brand_info_df.drop(deleterow)

    #Trier par ordre croissant et supprimer les champs de différence et d'identifiant
    brand_info_df = brand_info_df.sort_values("differ")
    brand_info_df = brand_info_df.drop(columns=["id", "differ"])

    #Limite de nombre
    brand_risk_near = brand_info_df.head(num_fund_obj)

    return brand_risk_near


#Obtenez des enregistrements de type dictionnaire.
    brand_info = MutualFund.objects.values(
        "id", "company", "fund_name", "risk")

    #Convertir en DataFrame
    brand_info_df = pd.DataFrame(brand_info)


Dans cette partie, l'enregistrement est acquis en spécifiant le champ à acquérir à partir de la base de données, et il est converti en type DataFrame après avoir été transformé en une liste de dictionnaires. Ensuite, dans brand_info_df, les colonnes seront une table qui représente les enregistrements dans chaque champ et ligne. Cette fois, nous devons calculer la différence de risque (rendement) entre l'action désignée et les autres actions, nous allons donc les acquérir toutes pour le moment.

python



 #Extraire les champs de risque des stocks désignés de DF
    find_obj = brand_info_df[brand_info_df["id"] == fund_id]
    risk_col = find_obj["risk"]

Puis modifiez le DataFrame. Cette fois, le champ id contient la valeur de la clé primaire, ce qui signifie que le champ id de brand_info_df identifie la ligne qui correspond à fund_id. Et cette fois, je veux les informations du champ de risque de la ligne spécifiée, donc je vais l'extraire davantage.

python



    #Créez un champ pour saisir le résultat du calcul de la différence de risque
    brand_info_df["differ"] = np.nan

    #Stockez la valeur de la différence de risque dans le champ de différence et rendez la valeur absolue.
    brand_info_df["differ"] = brand_info_df.apply(risk_differ, axis=1).abs()

    #Supprimer la ligne d'informations de la marque spécifiée par l'argument
    deleterow = brand_info_df.index[brand_info_df["id"] == fund_id]
    brand_info_df = brand_info_df.drop(deleterow)

    #Trier par ordre croissant et supprimer les champs de différence et d'identifiant
    brand_info_df = brand_info_df.sort_values("differ")
    brand_info_df = brand_info_df.drop(columns=["id", "differ"])

    #Limite de nombre
    brand_risk_near = brand_info_df.head(num_fund_obj)

    return brand_risk_near


Ici, nous effectuerons des opérations de type DataFrame sérieusement. Ce que vous devez implémenter avec cette fonction est de ** calculer la valeur absolue du problème spécifié et des autres problèmes enregistrés dans l'enregistrement, et de trier par ordre croissant **. Cependant, je ne pouvais pas écrire le processus uniquement avec l'ensemble de requêtes (orthographe qui extrait les données de la base de données), donc je l'implémente de cette manière en utilisant Pandas. Alors peut-être que ce n'est pas mieux, alors ne le prenez pas trop, et si vous avez du code qui peut exprimer ce processus avec juste le jeu de requêtes, ce serait utile.

Parlons tranquilles, jetons un œil au code

Tout d'abord, puisque le modèle d'origine n'a pas de champ qui représente une valeur absolue, nous l'ajouterons dans le DataFrame. Créez un nouveau champ en utilisant np.nan de la bibliothèque appelée numpy et en mettant les valeurs manquantes dans le champ créé pour le moment. Ensuite, remplacez la valeur manquante par une valeur absolue. La méthode ʻApply () est une méthode pour appliquer une fonction à DataFrame. L'argument est sous la forme de ʻapply (fonction à appliquer, lieu à appliquer) . L'endroit à appliquer peut être spécifié sous forme d'élément, de colonne et de ligne. Par exemple, si ʻaxis = 1comme cette fois-ci, il sera appliqué à chaque ligne de DataFrame. ʻAbs ()est une méthode qui renvoie une valeur absolue. Concernant risk_differ

python



def risk_differ(x):
    return risk_col - x.loc["risk"]

Est défini comme. Étant donné que risk_col contient la valeur de risque du stock spécifié, vous devez en soustraire la valeur de risque de l'enregistrement de chaque ligne. Cela insérera une valeur absolue dans brand_info_df [" diffèrent "] sur chaque ligne.

À ce stade, tout ce que vous avez à faire est d'organiser l'apparence. Tout d'abord, si cela reste tel quel, les stocks désignés seront toujours inclus dans le tableau. Cette fois, la différence de risque (rendement) par rapport à l'action désignée est faible = le processus consiste à répertorier les actions présentant un risque (rendement) similaire à l'action désignée. La ligne de la marque spécifiée sera supprimée. Tout d'abord, affectez la ligne extraite de la marque spécifiée à la variable delete row. Cette fois, de la méthode get_loc (), utilisez ʻindexpour obtenir le numéro de ligne de la marque spécifiée et le remplacer. Ensuite, l'assigner à l'argument de la méthodedrop ()` termine la suppression.

Vient ensuite le tri. Il existe différentes manières de trier un DataFrame, mais cette fois nous voulons trier en se référant aux valeurs, nous allons donc utiliser la méthode sort_values () qui trie les éléments. L'argument spécifie le champ que vous voulez trier. Au fait, si vous voulez trier par ordre décroissant, renvoyez ʻascending = Falsedans le deuxième argument. Après cela, les champs inutiles lors de l'affichage sur l'écran réel sont supprimés par la méthode précédentedrop (). Enfin, utilisez la méthode head ()` pour obtenir le nombre spécifié d'éléments depuis le début et le renvoyer avec return. Après cela, si vous faites une version de retour de ceci tel quel, le travail est terminé.

Dans ce projet, j'ai appris qu'il est possible de convertir les informations acquises de la base de données en un DataFrame et de renvoyer celui traité.

Application 2

Jusqu'à présent, nous avons traité le DataFrame, mais si vous vous référez au champ de l'enregistrement acquis et effectuez le traitement d'agrégation, vous pouvez également le faire dans la catégorie Opération DB. A titre d'exemple, le traitement est le suivant.

python



def find_fund_popular_user(fund_id, num_fund_obj):
    """
Extraire d'autres marques que la personne qui possède l'argument marque a

    Arguments:
        fund_id : int
        num_fund_obj : int

    Returns:
        fund_list : list
    """
    #Recherchez le modèle Portfolio à partir du problème de l'argument et extrayez les utilisateurs qui ont le problème de l'argument
    query = Portfolio.objects.filter(mutual_fund_obj__id__exact=fund_id)

    #Identifiant d'utilisateur(customuser_obj)Extraire uniquement dans la liste
    query = query.values_list('customuser_obj', flat=True)

    #Extraire tous les enregistrements contenant l'ID extrait
    customuser_obj_id_list = Portfolio.objects.filter(customuser_obj__in=query)

    #Jouez la marque de l'argument
    customuser_obj_id_list = Portfolio.objects.exclude(
        mutual_fund_obj__id__exact=fund_id)

    #Cette fois le fonds_id(mutual_fund_obj)Extraction
    mutual_fund_obj_list = customuser_obj_id_list.values('mutual_fund_obj')

    #Agréger le nombre d'occurrences et obtenir le nombre d'arguments du haut
    fund_count = mutual_fund_obj_list.annotate(portfolio_fund_count=Count(
        expression='mutual_fund_obj'))

    fund_count_list = fund_count.order_by(
        '-portfolio_fund_count')[0:num_fund_obj]

    #utilisation pour, fonds_count_Obtient les objets MutualFund correspondants pour le nombre de listes, les stocke dans une liste vide et les renvoie.
    fund_list = []
    for fund_record in fund_count_list:
        fund = MutualFund.objects.get(pk=fund_record['mutual_fund_obj'])
        fund_list.append(fund)

    return fund_list


python



    #Recherchez le modèle Portfolio à partir du problème de l'argument et extrayez les utilisateurs qui ont le problème de l'argument
    query = Portfolio.objects.filter(mutual_fund_obj__id__exact=fund_id)

    #Identifiant d'utilisateur(customuser_obj)Extraire uniquement dans la liste
    query = query.values_list('customuser_obj', flat=True)

    #Extraire tous les enregistrements contenant l'ID extrait
    customuser_obj_id_list = Portfolio.objects.filter(customuser_obj__in=query)

    #Jouez la marque de l'argument
    customuser_obj_id_list = Portfolio.objects.exclude(mutual_fund_obj__id__exact=fund_id)

    #Cette fois le fonds_id(mutual_fund_obj)Extraction
    mutual_fund_obj_list = customuser_obj_id_list.values('mutual_fund_obj')


Tout d'abord, cette partie a un flux similaire à celui d'avant. La différence est qu'il obtient des informations à partir de modèles associés. Le modèle «Portfolio» est lié au modèle «MutualFund» et au modèle «CustomUser», qui ne sont pas référencés dans ce processus. Le modèle «Portfolio» est le côté qui référence chaque modèle. Voir l'image ci-dessous pour ce qui se passe.

2020-06-27_03h02_47.png

Comme vous pouvez le voir, les champs «Obj de l'utilisateur personnalisé» et «Obj du fonds commun» sont des menus déroulants. Cela signifie que le champ «Customuser obj» contient des informations sur le modèle «CustomUser» référencé par la clé externe, et le champ «Mutual fund obj» fait également référence au «MutualFund» par la clé externe. Il montre que toutes les informations de l'enregistrement de sont emballées. En d'autres termes, si vous connaissez la clé externe, vous pouvez extraire les informations du modèle MutualFund du modèle Portfolio. C'est ce que fait la première ligne de code ci-dessus.

Cette fois, tout d'abord, je veux extraire les utilisateurs qui ont une marque avec pk = fund_id dans le modèle MutualFund qui a une marque comme argument = marque enregistrée. Cela signifie filtrer par la valeur de l'id dans le champ Objet du fonds commun de placement. À ce stade, si vous souhaitez faire référence à la valeur du champ référencé Nom du champ contenant les informations référencées__ Le nom du champ auquel vous voulez faire référence __exact = ~. Puisque ʻexactest une option appelée correspondance exacte, cette fois nous allons extraire celle qui correspond exactement à fund_id. Ensuite, les utilisateurs qui ont la marque spécifiée seront extraits, donc cette fois, utilisez la méthodevalue_list ()pour extraire leCustomuser obj` qui est plein d'informations utilisateur dans la liste.

À ce stade, je souhaite extraire les marques appartenant aux utilisateurs extraits, je vais donc filtrer à nouveau le modèle Portfolio. Ici, j'ai extrait Customuser obj de la liste plus tôt pour l'utiliser comme condition de recherche pour le filtre. En appliquant la notation de référence plus tôt, vous pouvez définir la condition de recherche sur lorsque le champ référencé contient ~ en définissant le nom de champ __in = ~qui est rempli avec les informations référencées. .. Bien sûr, si vous l'extrayez, la marque de l'argument est également incluse, donc excluez-la avec la méthode ʻexclude (). À ce stade, nous avons pu extraire des problèmes autres que ceux spécifiés par les utilisateurs avec le problème spécifié, mais puisque nous n'avons besoin que du champ mutual_fund_obj pour l'agrégation. Enfin, convertissez le champ mutual_fund_obj en type dictionnaire.

Quand vous arrivez à ce point, le reste est le processus d'agrégation.

Il existe plusieurs façons d'agréger les requêtes et les ensembles de requêtes, mais le ʻannotate () utilisé cette fois est une méthode qui agrège les ensembles de requêtes. Il existe d'autres méthodes d'agrégation par rapport à un ensemble de requêtes, ʻaggregate () , mais ʻannotate ()sera utilisé pour les modèles qui ont des relations. Plus précisément, il semble être utilisé lorsque vous souhaitez agréger pour le champ qui contient les informations du modèle référencé. Cette fois, je souhaite implémenter une fonction qui ** trie et affiche les autres marques appartenant aux utilisateurs avec l'argument marque spécifié par ordre de popularité (la plupart des utilisateurs ont cette marque) **. Comme nous l'avons préparé dans le processus jusqu'à présent, nous voulons effectuer un traitement d'agrégation surmutual_fund_obj, donc nous utiliserons ʻannotate (). La partie de code réelle est la suivante, vérifions-la.

python



    #Agréger le nombre d'occurrences et obtenir le nombre d'arguments du haut
    fund_count = mutual_fund_obj_list.annotate(portfolio_fund_count=Count(
        expression='mutual_fund_obj'))

    fund_count_list = fund_count.order_by(
        '-portfolio_fund_count')[0:num_fund_obj]

    #utilisation pour, fonds_count_Obtient les objets MutualFund correspondants pour le nombre de listes, les stocke dans une liste vide et les renvoie.
    fund_list = []
    for fund_record in fund_count_list:
        #Je veux des données de marque, alors financez_count_fonds avec pour stocké dans la liste_Mutuelle récupérée dans le dossier_fund_Obtenez contre MutualFund en utilisant obj()multiplier
        fund = MutualFund.objects.get(pk=fund_record['mutual_fund_obj'])
        fund_list.append(fund)

    return fund_list


Comment était mutual_fund_obj_list?


    #Jouez la marque de l'argument
    customuser_obj_id_list = Portfolio.objects.exclude(mutual_fund_obj__id__exact=fund_id)

    #Cette fois le fonds_id(mutual_fund_obj)Extraction
    mutual_fund_obj_list = customuser_obj_id_list.values('mutual_fund_obj')

C'était comme ça. Sur cette base, si vous expliquez ʻannotate () `

mutual_fund_obj_list.annotate(portfolio_fund_count=Count(expression='mutual_fund_obj'))

Dans cette partie, créez un champ portfolio_fund_count dans l'objet Portfolio et pensez que le résultat de l'exécution de la méthode Count () y est inséré. J'ai fait le processus de création d'un nouveau champ avec DataFrame et d'y insérer le résultat du calcul, mais l'image est similaire. Count (expression = 'mutual_fund_obj') est le processus de comptage du nombre de mutual_fund_objs apparus. À ce stade, les informations agrégées sont les informations qui se réfèrent au contenu de «mutual_fund_obj». Donc pour le dire très grossièrement

La marque A appartient à 5 utilisateurs
La marque B appartient à 3 utilisateurs

……


Sera agrégé. (L'exemple ci-dessus est juste une image) Après cela, vous pouvez trier les résultats agrégés dans l'ordre croissant par ʻorder_by. Pour la partie [0: num_fund_obj], le nombre d'acquisitions est entré dans num_fund_obj`.

Lorsque cela est fait, utilisez l'instruction for pour la dernière fund_count_list pour transmettre les données au modèle, et stockez les données dans une liste vide pour terminer le travail.

(pk=fund_record['mutual_fund_obj'])

Cette partie spécifie pk avec les informations de mutual_fund_obj extraites par l'instruction for. C'est parce que mutual_fund_obj contient naturellement des informations sur la clé primaire de la marque.

Création d'un processus (Views.py) pour transmettre des données à un modèle

Une fois les données prêtes, nous écrirons le processus de transmission au modèle pour affichage à l'écran. Le code est ci-dessous.


class FundDetail(LoginRequiredMixin, View):

    """
-Obtenir des informations sur des actions avec des risques similaires et des actions avec des rendements similaires
・ Extrayez d'autres marques que la personne qui possède l'argument marque a
    """

    def get(self, request, fund_id, *args, **kwargs):

        #Réglage du numéro d'acquisition
        num_fund_obj = 5

        #Remplacez une liste d'actions présentant des risques et des rendements similaires par des variables
        brand_risk_near_list = find_fund_near_risk(fund_id, num_fund_obj)
        brand_return_near_list = find_fund_near_return(fund_id, num_fund_obj)

        #Informations d'en-tête DataFrame
        brand_risk_near_header = brand_risk_near_list.columns.tolist()
        brand_return_near_header = brand_return_near_list.columns.tolist()

        #Informations sur le contenu DataFrame
        brand_risk_near_contents = brand_risk_near_list.values.tolist()
        brand_return_near_contents = brand_return_near_list.values.tolist()

        #Obtenez les autres marques que l'utilisateur qui a l'argument marque a du haut du numéro enregistré
        fund_popular_list = find_fund_popular_user(fund_id, num_fund_obj)

        context = {
            'risk_header': brand_risk_near_header,
            'risk_contents': brand_risk_near_contents,
            'return_header': brand_return_near_header,
            'return_contents': brand_return_near_contents,
            'popular_user_funds': fund_popular_list,
        }
        return render(request, 'fund/fund_detail.html', context=context)



Cette fois, nous passerons des données et des objets de type DataFrame, mais la méthode de passage est différente pour chacun. Premièrement, dans le cas du type DataFrame, les données sont transmises séparément pour l'en-tête (informations de champ) et le contenu (valeur de chaque champ) dans views.py. Dans le cas d'un objet, il sera transmis tel quel. Après avoir stocké ces données dans des variables, définissez-les pour qu'elles puissent être appelées par le modèle dans context. Par exemple, si vous souhaitez appeler "marque_risk_near_header" sur le modèle, écrivez "en-tête_risque". Après avoir atteint ce point, utilisez la méthode de rendu pour passer context au modèle et le récupérer avec for.

Le modèle est le suivant.



<div class="row">
    {% comment %}Liste des informations boursières présentant des risques similaires{% endcomment %}
    <div class="col">
        <h5>Actions présentant un risque similaire à ce stock</h5>
        <div class="">
            <table class="table">
                    <thead>
                    <tr>{% for row in risk_header %}
                        <th>{{ row }}</th>{% endfor %}</tr>
                    </thead>
                    <tbody>
                    {% for i in risk_contents %}
                        <tr>{% for row1 in i %}
                            <td>{{ row1 }}</td>{% endfor %}</tr>
                    {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>
            {% comment %}Liste des informations boursières avec des retours similaires{% endcomment %}
        <div class="col">
            <h5>Stocks avec des rendements similaires pour ce stock</h5>
            <div class="">
                <table class="table">
                    <thead>
                    <tr>{% for row in return_header %}
                        <th>{{ row }}</th>{% endfor %}</tr>
                    </thead>
                    <tbody>
                    {% for i in return_contents %}
                        <tr>{% for row1 in i %}
                            <td>{{ row1 }}</td>{% endfor %}</tr>
                    {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>
    </div>
            <div class="">
            <h5>Les personnes qui achètent cette marque achètent également cette marque</h5>
            <div class="">
                <table class="table">
                    <thead>
                    <tr>
                        <th>Nom du fonds</th>
                        <th>revenir</th>
                        <th>risque</th>
                    </tr>
                    </thead>

                    <tbody>
                    {% for fund in popular_user_funds %}
                        <tr>
                            <th>
                                <a href=" /fund/detail/{{ fund.id }} ">{{ fund.fund_name }}</a>
                            </th>
                            <th>{{ fund.return_percent }}</th>
                            <th>{{ fund.risk }}</th>
                        </tr>
                    {% endfor %}

                    </tbody>
                </table>
            </div>
        </div>
    </div>

Une chose à laquelle il faut faire attention est de savoir comment récupérer risk_contents. Celui-ci contiendra la valeur de chaque champ dans le DataFrame, qui est converti en une liste avec values.tolist () et transmis. Les données échangées cette fois ont des lignes et des colonnes comme indiqué ci-dessous ... Ce n'est pas grave.

#       col1  col2  col3
# row1     0     1     2
# row2     3     4     5

#Df le DataFrame ci-dessus.values.tolist()Lorsqu'il est stocké dans, il devient comme suit

# [[0, 1, 2], [3, 4, 5]]

#Au fait, les colonnes de ce DataFrame.tolist()Est stocké comme suit

# # ['col1', 'col2', 'col3']

Ensuite, par exemple, je veux récupérer les données de row1! Même si cela devient, il existe 3 types de col1 ~ 3, et inversement, si vous voulez récupérer les données de col1, vous pouvez avoir row1 ~ 2. Dans ce cas, la méthode de stockage dans la liste n'est pas le tableau principal comme dans le résultat de columns.tolist (), mais il ne peut pas être récupéré correctement à moins qu'il ne s'agisse d'un tableau secondaire, donc stockez-le comme dans l'exemple ci-dessus. Imaginez que vous l'êtes.

La façon de récupérer un objet dans un modèle est identique à une instruction for normale. Premièrement, {% for fund in popular_user_funds%} transmet chaque mutual_fund_obj à la variable fund. Après cela, comme je l'ai mentionné à plusieurs reprises, le mutual_fund_obj du modèle Portfolio passé cette fois est lié à MutualFund, donc c'est OK si vous l'écrivez sous la forme de fund. Information du champ du modèle MutualFund que vous voulez extraire. Sera.

référence

Obtenir les numéros de ligne et de colonne pour pandas.DataFrame sort_values, sort_index pour trier pandas.DataFrame, Series [Flask] Passer pandas.Series et pandas.DataFrame au côté client Convertir les listes standard pandas.DataFrame, Series et Python entre elles Opération de base Pandas fréquemment utilisée dans l'analyse des données Résumé des opérations de la base de données Django Document Django 1 Document Django 2 Django Reverse Pull Cheet Sheet (Query Set) Traitement agrégé avec Django

Recommended Posts