1
votes

Créer un dictionnaire de dictés à partir d'une seule liste - Python3

Python 3.6.5 / 3.7.1 sous Linux

J'ai du mal à créer un dictionnaire avec des dictionnaires comme valeurs.

Je veux créer un dictionnaire à partir d'une liste de données de date et d'heure (finalement pour créer graphiques avec bokeh).

Cela a dû être demandé auparavant, mais je ne trouve pas un ensemble de termes de recherche qui renvoie un résultat qui clarifie les choses pour moi.

nb I ' Je suis essentiellement un codeur amateur, et je ne pense pas facilement à un algorithme comme un vrai programmeur.

Les données sont dans une liste (maximum 3200 éléments): Chaque élément est un enregistrement de l'occurrence d'un événement à une date dans une période d'horloge d'une heure.

Ainsi; ['03 / 01/19 09:00 ', '03 / 01/19 09:00', '03 / 01/19 09:00 ',] indique 3 événements entre 0900-1000 le 03/01/2019.

Seules les périodes d'horloge avec des événements sont enregistrées, donc si aucun événement, aucun horodatage.

Le format de la date est jjmmaa p>

Exemple de données:

{i.split()[0]:{} for i in dtl}

Le dictionnaire souhaité ressemblerait à ceci:

dtd = {
    '03/01/19': {
         '00': 0, '01': 0, '02': 0, '03': 0, '04': 0, '05': 0,
         '06': 0, '07': 0, '08': 0, '09': 3, '10': 2, '11': 1,
         '12': 5, '13': 0, '14': 0, '15': 0, '16': 0, '17': 1,
         '18': 0, '19': 0, '20': 0, '21': 1, '22': 0, '23': 0,
     },
     '04/01/19': {
         '00': 0, ... '23': 0
     },
     '05/01/19': {
         '00': 0, ... 
     } ... etc
}

Je peux clairement initialiser un dictionnaire avec au moins les clés:

dtl = [
    '06/01/19 12:00', '06/01/19 12:00', '06/01/19 11:00', '05/01/19 21:00',
    '05/01/19 17:00', '05/01/19 17:00', '05/01/19 14:00', '03/01/19 21:00',
    '03/01/19 17:00', '03/01/19 12:00', '03/01/19 12:00', '03/01/19 12:00',
    '03/01/19 12:00', '03/01/19 12:00', '03/01/19 11:00', '03/01/19 10:00',
    '03/01/19 10:00', '03/01/19 09:00','03/01/19 09:00','03/01/19 09:00',
]

Mais alors je ne peux pas comprendre ce que je dois faire pour mettre à jour les sous-titres avec les décomptes, et ainsi de suite ' t voir un moyen de passer de la liste d'origine au dictionnaire souhaité. Je tourne en rond!


2 commentaires

Juste pour confirmer que toutes les heures sont à l'heure? Vous ne verrez aucun 09:30 ?


@hqkhan correct


3 Réponses :


2
votes

5 commentaires

Légèrement confus par la remarque "utilisez-les pour initialiser un defaultdict qui renverra des zéros pour les heures manquantes:" comme dans l'exemple de sortie, les 'heures manquantes' ne sont pas affichées; Mais j'ai peut-être mal compris l'intention.


@CodeRedoted Donc, cela a à voir avec la façon dont defaultdict fonctionne. Il initialisera votre valeur à quelque chose si la clé que vous avez essayée n'était pas en fait à l'intérieur du dict . Par exemple si test = {1: 20, 2: 25} . En supposant que test est un defaultdict , vous avez essayé de lancer test [15] , même si 15 n'existe pas à l'intérieur test , vous récupérerez 0 et non un KeyError . Le même comportement peut être fait en utilisant .get (key, default_value) Je crois, mais defaultdict rend les choses bien.


@hqkhan. L'avantage de defaultdict par rapport à get ou setdefault est que defaultdict n'appelle que le constructeur que vous passez lorsque la clé est disparu. Avec les méthodes dict , vous appelez le constructeur à chaque fois, avant d'appeler la méthode, ce qui entraîne une surcharge généralement inoffensive mais inutile.


@MadPhysicist Nice. Bon à savoir.


@CodeRedaced. Un defaultdict n'affiche que les clés que vous avez définies, mais il vous permet d'interroger n'importe quelle clé. dtd ['blah'] renverra [] , tandis que dtd [03/01/19] ['blah'] renverra 0. Comme il est logique que vous ne souhaitiez pas que cela se produise à des heures et des dates arbitraires, j'ai ajouté un extrait de code pour convertir rapidement en un dictionnaire imbriqué normal à ma réponse.



2
votes

Je suggérerais l'utilisation de collections.defaultdict car certains de vos comptes peuvent être 0.

Voici une option:

{'06/01/19': {'00': 0, '01': 0, '02': 0, '03': 0, '04': 0, '05': 0, '06': 0, '07': 0, '08': 0, '09': 0, '10': 0, '11': 1, '12': 2, '13': 0, '14': 0, '15': 0, '16': 0, '17': 0, '18': 0, '19': 0, '20': 0, '21': 0, '22': 0, '23': 0}, '05/01/19': {'00': 0, '01': 0, '02': 0, '03': 0, '04': 0, '05': 0, '06': 0, '07': 0, '08': 0, '09': 0, '10': 0, '11': 0, '12': 0, '13': 0, '14': 1, '15': 0, '16': 0, '17': 2, '18': 0, '19': 0, '20': 0, '21': 1, '22': 0, '23': 0}, '03/01/19': {'00': 0, '01': 0, '02': 0, '03': 0, '04': 0, '05': 0, '06': 0, '07': 0, '08': 0, '09': 3, '10': 2, '11': 1, '12': 5, '13': 0, '14': 0, '15': 0, '16': 0, '17': 1, '18': 0, '19': 0, '20': 0, '21': 1, '22': 0, '23': 0}}

Sortie (en utilisant pprint):

times = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10',
         '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21',
         '22', '23']

dtl = ['06/01/19 12:00', '06/01/19 12:00', '06/01/19 11:00', 
       '05/01/19 21:00', '05/01/19 17:00', '05/01/19 17:00', 
       '05/01/19 14:00', '03/01/19 21:00', '03/01/19 17:00',
       '03/01/19 12:00', '03/01/19 12:00', '03/01/19 12:00', 
       '03/01/19 12:00', '03/01/19 12:00', '03/01/19 11:00', 
       '03/01/19 10:00', '03/01/19 10:00', '03/01/19 09:00',
       '03/01/19 09:00','03/01/19 09:00']

result = {date_time.split()[0] : {time : 0 for time in times} for date_time in dtl}

for date_time in dtl:
    date, time = date_time.split()
    result[date][time.split(':')[0]] += 1

Si vous voulez vraiment afficher le 0 pour l'impression, je ne le fais pas. Je vois vraiment un moyen de conserver un tableau de heures comme je l'ai fait ici et d'initialiser votre dict de cette façon.

defaultdict(<function <lambda> at 0x7f20d5c37c80>,
            {'03/01/19': defaultdict(<class 'int'>,
                                     {'09': 3,
                                      '10': 2,
                                      '11': 1,
                                      '12': 5,
                                      '17': 1,
                                      '21': 1}),
             '05/01/19': defaultdict(<class 'int'>,
                                     {'14': 1,
                                      '17': 2,
                                      '21': 1}),
             '06/01/19': defaultdict(<class 'int'>, {'12': 2, '11': 1})})

Résultat ci-dessous:

from collections import defaultdict

dtl = ['06/01/19 12:00', '06/01/19 12:00', '06/01/19 11:00', 
       '05/01/19 21:00', '05/01/19 17:00', '05/01/19 17:00', 
       '05/01/19 14:00', '03/01/19 21:00', '03/01/19 17:00',
       '03/01/19 12:00', '03/01/19 12:00', '03/01/19 12:00', 
       '03/01/19 12:00', '03/01/19 12:00', '03/01/19 11:00', 
       '03/01/19 10:00', '03/01/19 10:00', '03/01/19 09:00',
       '03/01/19 09:00','03/01/19 09:00',]

# Nested defaultdict
result = defaultdict(lambda: defaultdict(int))

for date_time in dtl:
    date, time = date_time.split()
    result[date][time.split(':')[0]] += 1


1 commentaires

Cette réponse et celle de @ mad-physicist sont pertinentes et extrêmement utiles, mais celle-ci a l'avantage pour moi car elle permet de remplir les valeurs «vides» dans le dict final.



0
votes

Une manière rapide et sale est la suivante:

#!/usr/bin/env python3

def convert(dt):
    ret = {}
    for elem in dt:
        d,t = elem.split()
        t = t.split(":")[0]
        # not a valid value
        if not d: pass

        # we inserted d already
        if d in ret:
            if t in ret[d]:
                ret[d][t] += 1
        else:
            ret[d] = {'00': 0, '01': 0, '02': 0, '03': 0, '04': 0, '05': 0,
                    '06': 0, '07': 0, '08': 0, '09': 0, '10': 0, '11': 0, 
                    '12': 0, '13': 0, '14': 0, '15': 0, '16': 0, '17': 0, 
                    '18': 0, '19': 0, '20': 0, '21': 0, '22': 0, '23': 0 }
    return ret

dtl = ['06/01/19 12:00', '06/01/19 12:00', '06/01/19 11:00', '05/01/19 21:00', '05/01/19 17:00', '05/01/19 17:00', '05/01/19 14:00', '03/01/19 21:00', '03/01/19 17:00','03/01/19 12:00', '03/01/19 12:00', '03/01/19 12:00', '03/01/19 12:00', '03/01/19 12:00', '03/01/19 11:00', '03/01/19 10:00', '03/01/19 10:00', '03/01/19 09:00','03/01/19 09:00','03/01/19 09:00']

print(convert(dtl))


2 commentaires

ret [d] = {} . Avez-vous oublié d'insérer la première fois et d'ajouter 1? De même, dans la partie if , vous devriez commencer par 1 et non par 0.


oui, vous avez raison, n'était pas non plus dans le bon format.