2
votes

Compter l'occurrence de plusieurs éléments pour un élément maître spécifique dans un tableau 2D à l'aide de python

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


0 commentaires

3 Réponses :


3
votes

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.


2 commentaires

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



0
votes

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}


0 commentaires

1
votes

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.


0 commentaires