J'ai des listes 2D avec chaque ligne contenant des entrées COMMON_NAME et des informations supplémentaires. Je veux trouver la somme du nombre d'éléments MYFR appartenant à chaque COMMON_NAME.
For example, this is my list [['SOME TEXT', 'COMMON_NAME1', None, 'CHOC', 'MYFR01'], ['SOME TEXT2', 'COMMON_NAME1', None, 'ABC', 'MYFR02'], ['SOME TEXT3', 'COMMON_NAME1', None, 'XYZ', 'MYFR03'], ['SOME TEXT4', 'COMMON_NAME2', None, 'XYZ', 'STRAWBERRY'], ['SOME TEXT5', 'COMMON_NAME2', None, 'XYZ', 'MYFR01'], ['SOME TEXT6', 'COMMON_NAME2', None, 'XYZ', 'MYFR02'], ['SOME TEXT7', 'COMMON_NAME2', None, 'XYZ', 'APPLE']
Pour chaque COMMOM_NAME, je veux trouver la somme des occurrences si elles sont dans {'MYFR01', 'MYFR02', 'MYFR03'}
Telles que dans cet exemple je veux obtenir COMMON_NAME1 = 3 et COMMON_NAME2 = 2
Existe-t-il un moyen simple d'y parvenir?
Merci
3 Réponses :
Voici une solution avec collections.Counter
:
>>> tgt = {'MYFR01', 'MYFR02', 'MYFR03'} >>> c = Counter(i[1] for i in data if i[-1] in tgt) >>> c Counter({'COMMON_NAME1': 3, 'COMMON_NAME2': 2})
Cela suppose que vos choix de cibles commenceront toujours par MYFR
. En lisant un peu plus attentivement votre question, vous pouvez également utiliser:
>>> from collections import Counter >>> data = [['SOME TEXT', 'COMMON_NAME1', None, 'CHOC', 'MYFR01'], ... ['SOME TEXT2', 'COMMON_NAME1', None, 'ABC', 'MYFR02'], ... ['SOME TEXT3', 'COMMON_NAME1', None, 'XYZ', 'MYFR03'], ... ['SOME TEXT4', 'COMMON_NAME2', None, 'XYZ', 'STRAWBERRY'], ... ['SOME TEXT5', 'COMMON_NAME2', None, 'XYZ', 'MYFR01'], ... ['SOME TEXT6', 'COMMON_NAME2', None, 'XYZ', 'MYFR02'], ... ['SOME TEXT7', 'COMMON_NAME2', None, 'XYZ', 'APPLE']] >>> c = Counter(i[1] for i in data if i[-1].startswith('MYFR')) >>> c Counter({'COMMON_NAME1': 3, 'COMMON_NAME2': 2})
La bonne chose à propos de Counter
(une sous-classe de dict
) est qu'il peut accepter un expression du générateur . Cela signifie que vous n'avez pas besoin de matérialiser les éléments "filtrés" dans une structure de données intermédiaire telle qu'une liste.
L'exécution de ces deux solutions donne une valeur à Counter () avec len = 0 sur mon python 3.7. Y a-t-il quelque chose qui me manque?
Peu importe, c'était juste la valeur de décalage incorrecte. Merci
Nous allons garder un dictionnaire mappant les valeurs de COMMON_NAME
à des ensembles de valeurs MYFR
, puis mesurer la taille de ces ensembles à la fin. Cela détermine le nombre d'éléments uniques MYFR
pour chaque COMMON_NAME
.
from collections import defaultdict d = defaultdict(set) for first, common_name, *others, last in my_list: if common_name.startswith("COMMON_NAME"): # Maybe unneccessary if last.startswith("MYFR"): d[common_name].add(last) d = {k: len(v) for k, v in d.items()} # {'COMMON_NAME1': 3, 'COMMON_NAME2': 2}
Vous pouvez également utiliser pandas
pour cela:
from itertools import groupby second = itemgetter(1) last = itemgetter(-1) for k, v in groupby(data, key=second): print(k, len([last(i) for i in v if last(i).startswith('MYFR')])) COMMON_NAME1 3 COMMON_NAME2 2
De plus, nous pouvons utiliser itertools:
import pandas as pd df = pd.DataFrame(data, columns=['text', 'cname', 'none', 'code', 'name']) text cname none code name 0 SOME TEXT COMMON_NAME1 None CHOC MYFR01 1 SOME TEXT2 COMMON_NAME1 None ABC MYFR02 2 SOME TEXT3 COMMON_NAME1 None XYZ MYFR03 3 SOME TEXT4 COMMON_NAME2 None XYZ STRAWBERRY 4 SOME TEXT5 COMMON_NAME2 None XYZ MYFR01 5 SOME TEXT6 COMMON_NAME2 None XYZ MYFR02 6 SOME TEXT7 COMMON_NAME2 None XYZ APPLE df.loc[df['name'].str.contains('MYFR'), ['name', 'cname']] \ .groupby('cname', as_index=False) \ .count() cname name 0 COMMON_NAME1 3 1 COMMON_NAME2 2
La seule mise en garde ici est que les données doivent d'abord être triées.