Étant donné les deux listes suivantes, je veux compter le nombre d'occurrences de chaque élément inclus dans «a» en le pondérant avec la valeur de «b». Python est 3.7.5.
a = ["A", "B", "C", "A"]
b = [ 1 , 1 , 2 , 2 ]
c = hoge(a, b)
print(c)
production
{"A": 3, "B": 1, "C": 2} #Je veux ce genre de sortie
#La clé et la valeur peuvent être séparées
# (["A", "B", "C"], [3, 1, 2])
Supposons que vous souhaitiez compter le nombre de livres vendus jusqu'à présent dans une librairie pour chaque livre. [^ 1] Cependant, je n'ai que ** plusieurs données de table qui ont déjà été agrégées par mois **. Par souci de simplicité, imaginons les deux fichiers csv suivants.
■ 2020_01.csv
Nom du livre | Nombre de livres vendus |
---|---|
Book_A | 1 |
Book_B | 2 |
Book_C | 3 |
■ 2020_02.csv
Nom du livre | Nombre de livres vendus |
---|---|
Book_A | 2 |
Book_C | 1 |
Book_D | 3 |
La combinaison de ces deux données entraîne un problème de comptage avec des «éléments» et des «poids» comme décrit dans «Ce que vous voulez faire».
Il a été fabriqué par les trois méthodes suivantes. Je vous serais reconnaissant si vous pouviez me dire laquelle est la meilleure ou une autre méthode [^ 2].
étiquette
qui correspond uniquement au nom du livre et comptez le poids avec numpy.bincount
.collections.Counter
pour chaque table et ajoutez les objets Counter
pour toutes les tables.reduction
au lieu de l'instruction for.En utilisant la fonction bincount
de numpy
, vous pouvez compter tout en pondérant l'entrée.
Référence: Signification du poids dans numpy.bincount
Cependant, chaque élément que vous entrez dans np.bincount
** doit être un entier non négatif **.
numpy.bincount(x, weights=None, minlength=0) Count number of occurrences of each value in array of non-negative ints.
x : array_like, 1 dimension, nonnegative ints ---- Input array. weights : array_like, optional ---- Weights, array of the same shape as x. minlength : int, optional ---- A minimum number of bins for the output array. ---- New in version 1.6.0.
Par conséquent, pour utiliser «np.bincount», préparez une «étiquette» qui correspond uniquement au nom du livre. J'ai utilisé «LabelEncoder» de «sklearn» pour créer «label».
import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder
#Préparation des données
df_01 = pd.DataFrame([["Book_A", 1],
["Book_B", 2],
["Book_C", 3]],
columns=["Name", "Count"])
df_02 = pd.DataFrame([["Book_A", 2],
["Book_C", 1],
["Book_D", 3]],
columns=["Name", "Count"])
#Joindre la table
df_all = pd.concat([df_01, df_02])
#Le contenu est comme ça.
# | | Name | Count |
# |--:|:--|--:|
# | 0 | Book_A | 1 |
# | 1 | Book_B | 2 |
# | 2 | Book_C | 3 |
# | 0 | Book_A | 2 |
# | 1 | Book_C | 1 |
# | 2 | Book_D | 3 |
#LabelEncoder
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
encoded = le.fit_transform(df_all['Name'].values)
#Ajouter une nouvelle colonne d'étiquette
df_all["Label"] = encoded
# np.Comptage pondéré avec bincount
#En plus de la colonne Libellé, saisissez la colonne Nombre comme poids. Comme le résultat a un point décimal, je le convertis en int.
count_result = np.bincount(df_all["Label"], weights=df_all["Count"]).astype(int)
#Obtenez le nom correspondant au résultat
name_result = le.inverse_transform(range(len(result)))
#Créez le dictionnaire que vous voulez à la fin
result = dict(zip(name_result, count_result))
print(result)
production
{'Book_A': 3, 'Book_B': 2, 'Book_C': 4, 'Book_D': 3}
Vous pouvez également créer une étiquette
en utilisant np.unique
.
Vous pouvez obtenir le même résultat que fit_transform
de LabelEncoder
en définissant l'argument return_inverse
de np.unique
sur True.
De plus, vous pouvez également obtenir le nom correspondant (name_result
ci-dessus) à la fois.
# np.Encodage d'étiquettes à l'aide d'un
name_result, encoded = np.unique(df_all["Name"], return_inverse=True)
print(encoded)
print(name_result)
production
[0 1 2 0 2 3]
['Book_A' 'Book_B' 'Book_C' 'Book_D']
De plus, le comptage pondéré est possible en tournant l'instruction for sans utiliser np.bincount
[^ 3].
#Créez un tableau rempli de zéro avec la même longueur que le dictionnaire souhaité
unique_length = len(name_result)
count_result = np.zeros(unique_length, dtype=int)
#Extrayez uniquement les lignes de la table où codé correspond à i et calculez la somme des valeurs Count.
for i in range(unique_length):
count_result[i] = df_all.iloc[encoded==i]["Count"].sum().astype(int)
result = dict(zip(name_result, count_result))
print(result)
production
{'Book_A': 3, 'Book_B': 2, 'Book_C': 4, 'Book_D': 3}
Le module Counter
des collections du module standard` sera souvent introduit pour le comptage ** non pondéré **.
from collections import Counter
a = ["A", "B", "C", "A"]
#Donnez à Counter une liste et faites un comptage non pondéré
counter = Counter(a)
print(counter)
#L'accès aux éléments est le même que dans un dictionnaire
print("A:", counter["A"])
production
Counter({'A': 2, 'B': 1, 'C': 1})
A: 2
De plus, s'il a déjà été agrégé comme cette fois, vous pouvez créer un objet en le stockant dans le type de dictionnaire, puis en le passant.
counter = Counter(dict([["Book_A", 1],
["Book_B", 2],
["Book_C", 3]]))
print(counter)
production
Counter({'Book_A': 1, 'Book_B': 2, 'Book_C': 3})
D'ailleurs, cet objet Counter
peut être calculé.
Référence: Différentes manières de vérifier le nombre d'occurrences d'un élément avec Python Counter
Il semble que cet objectif puisse être atteint en calculant la somme.
from collections import Counter
a = ["A", "B", "C", "A"]
b = ["C", "D"]
counter_a = Counter(a)
counter_b = Counter(b)
#Peut être ajouté avec somme
counter_ab = sum([counter_a, counter_b], Counter())
print(counter_ab)
production
Counter({'A': 2, 'C': 2, 'B': 1, 'D': 1})
from collections import Counter
#Préparation des données
df_01 = pd.DataFrame([["Book_A", 1],
["Book_B", 2],
["Book_C", 3]],
columns=["Name", "Count"])
df_02 = pd.DataFrame([["Book_A", 2],
["Book_C", 1],
["Book_D", 3]],
columns=["Name", "Count"])
#Créer un compteur
counter_01 = Counter(dict(df_01[["Name", "Count"]].values))
counter_02 = Counter(dict(df_02[["Name", "Count"]].values))
#Calculez la somme
# *Supplément:Vous pouvez définir la valeur initiale du deuxième argument de sum.
#Cette fois, un compteur vide est défini comme valeur initiale. La valeur par défaut est 0(int)est.
result = sum([counter_01, counter_02], Counter())
print(result)
production
Counter({'Book_C': 4, 'Book_A': 3, 'Book_D': 3, 'Book_B': 2})
~~ Apparemment, les nombres sont triés par ordre décroissant. ~~
Si vous donnez au dictionnaire plusieurs «valeurs» pour la même «clé», elle sera écrasée par la dernière «valeur» donnée.
print( {"A": 1, "B": 2, "C": 3, "A":10} )
production
{'A': 10, 'B': 2, 'C': 3}
En utilisant cela, afin de mettre à jour la valeur de comptage d'une certaine clé
, il semble que ** récupère la valeur ** du dictionnaire existant, ajoute ** la valeur ** à ajouter et l'ajoute à la fin.
De plus, pour ajouter un élément après un dictionnaire existant, vous pouvez développer le dictionnaire en ajoutant \ * \ * (deux étoiles) à la variable.
Référence: [\ Python ] arguments de fonction \ * (étoile) et \ * \ * (étoile double)
#Dictionnaire existant
d = {"A": 1, "B": 2, "C": 3}
#Élément à valeur ajoutée
k = "A"
v = 10
#mise à jour
d = {**d, k: d[k]+v} # {"A": 1, "B": 2, "C": 3, "A": 1+10}Équivalent à
print(d)
production
{'A': 11, 'B': 2, 'C': 3}
Cependant, si vous spécifiez une «clé» qui n'existe pas dans le dictionnaire, une erreur se produira, vous ne pouvez donc pas ajouter une nouvelle «clé» telle quelle.
Par conséquent, utilisez la fonction get ()
de l'objet dictionnaire. Vous pouvez utiliser get ()
pour définir la valeur à renvoyer par défaut lorsque key
n'existe pas dans le dictionnaire.
Référence: Obtenir la valeur de la clé avec la méthode get du dictionnaire Python (la clé qui n'existe pas est OK)
d = {"A": 1, "B": 2, "C": 3}
#Spécifiez une clé existante
print(d.get("A", "NO KEY"))
#Spécifiez une clé qui n'existe pas
print(d.get("D", "NO KEY"))
production
1
NO KEY
Cela vous permet de gérer les ajouts et les mises à jour de la même manière en définissant la valeur par défaut sur «0». En utilisant le contenu ci-dessus, le code qui effectue le comptage pondéré en ajoutant / mettant à jour des valeurs dans un dictionnaire vide est le suivant.
import pandas as pd
from itertools import chain
#Préparation des données
import pandas as pd
from itertools import chain
from functools import reduce
#Préparation des données
df_01 = pd.DataFrame([["Book_A", 1],
["Book_B", 2],
["Book_C", 3]],
columns=["Name", "Count"])
df_02 = pd.DataFrame([["Book_A", 2],
["Book_C", 1],
["Book_D", 3]],
columns=["Name", "Count"])
#Convertir le bloc de données en dictionnaire
data1 = dict(df_01[["Name", "Count"]].values)
data2 = dict(df_02[["Name", "Count"]].values)
#Définition des fonctions
chain_items = lambda data : chain.from_iterable( d.items() for d in data ) #Combinez plusieurs dictionnaires"paire clé et valeur"Fonction qui retourne
add_elem = lambda acc, e : { **acc, e[0]: acc.get(e[0], 0) + e[1] } #Une fonction qui ajoute des éléments au dictionnaire et met à jour les valeurs
#Une fonction qui reçoit et fusionne plusieurs dictionnaires où la clé est un élément et la valeur est un poids
def merge_count(*data) :
result = {}
for e in chain_items(data) :
result = add_elem(result, e)
return result
print( merge_count(data1, data2) )
production
{'A': 3, 'B': 2, 'C': 4, 'D': 3}
réduire
au lieu de 3 pour l'instructionAvec «réduire», le traitement itératif est possible sans écrire une instruction for.
réduire
prend les arguments suivants.
from functools import reduce
func = lambda ans, x: ans * x
a = [1, 2, 3, 4]
start = 10
print(reduce(func, a, start))
production
240 # 10*1 = 10
# -> 10*2 = 20
# -> 20*3 = 60
# -> 60*4 = 240
Si vous reproduisez le merge_count
ci-dessus à l'aide de réduire
, ce sera comme suit.
from functools import reduce
merge_count = lambda *data : reduce( add_elem, chain_items(data), {} ) #Fusionner ci-dessus_Équivalent à compter
print( merge_count(data1, data2) )
production
{'A': 3, 'B': 2, 'C': 4, 'D': 3}
Le site suivant a été très utile pour «réduire». Référence: Introduction à la programmation fonctionnelle
Signification du poids dans numpy.bincount [Codage de variable de catégorie] (https://qiita.com/ground0state/items/f516b97c7a8641e474c4)
[[Python] Comptage des éléments de liste, comment utiliser les collections. Compteur] (https://qiita.com/ellio08/items/259388b511e24625c0d7) [Différentes façons de vérifier le nombre d'occurrences d'un élément avec Python Counter] (https://www.headboost.jp/python-counter/)
[\ [Python ] arguments de fonction \ * (étoile) et \ * \ * (double étoile)] (https://qiita.com/supersaiakujin/items/faee48d35f8d80daa1ac) [Introduction à la programmation fonctionnelle] (https://postd.cc/an-introduction-to-functional-programming/)
[^ 1]: J'ai donné un exemple concret approprié pour le rendre plus facile à transmettre, mais en réalité il a été utilisé pour agréger les résultats d'analyse morphologique de plusieurs documents. [^ 2]: Vitesse d'exécution, efficacité de la mémoire, etc ... [^ 3]: Je ne pouvais penser à rien d'autre que d'écrire une instruction for avec mes propres connaissances ... (à l'exclusion de la notation d'inclusion de liste).
Recommended Posts