2017-10-09 4 views
2

J'ai un dictionnaire où les clés sont datetime.datetime & les valeurs sont des listes de tweets. Donc, il ressemble à ceci:Filtrer la date dans les objets datetime par mois

{datetime.datetime(2017, 9, 30, 19, 55, 20) : ['this is some tweet text'], 
datetime.datetime(2017, 9, 30, 19, 55, 20) : ['this is another tweet']... 

J'essaie d'obtenir le nombre de tweets envoyés chaque mois de l'année. Jusqu'à présent, j'ai ...

startDate = 10 
endDate= 11 
start = True 
while start: 

    for k,v in tweetDict.items(): 
     endDate-=1 
     startDate-=1 

     datetimeStart = datetime(2017, startDate, 1) 
     datetimeEnd = datetime(2017,endDate, 1) 

     print(datetimeStart, datetimeEnd) 

     if datetimeStart < k < datetimeEnd: 
      print(v) 
     if endDate == 2: 
      start = False 
      break 

qui imprime seulement (je suis au courant de la déclaration d'impression) ...

2017-08-01 00:00:00 2017-09-01 00:00:00 
2017-07-01 00:00:00 2017-08-01 00:00:00 
2017-06-01 00:00:00 2017-07-01 00:00:00 
2017-05-01 00:00:00 2017-06-01 00:00:00 
2017-04-01 00:00:00 2017-05-01 00:00:00 
2017-03-01 00:00:00 2017-04-01 00:00:00 
2017-02-01 00:00:00 2017-03-01 00:00:00 
2017-01-01 00:00:00 2017-02-01 00:00:00 

et non les tweets eux-mêmes. Je m'attendais à quelque chose comme ...

2017-08-01 00:00:00 2017-09-01 00:00:00 
['heres a tweet'] 
['theres a tweet'] 
2017-07-01 00:00:00 2017-08-01 00:00:00 
['there only 1 tweet for this month'].... 

Je suis coincé, comment puis-je y parvenir?

Répondre

1

Vous pouvez juste group by le mois, au lieu d'essayer de soustraire/comparer différents mois:

>>> d = {datetime.datetime(2017, 9, 30, 19, 55, 20): ['this is some tweet text'], 
     datetime.datetime(2017, 9, 30, 20, 55, 20): ['this is another tweet'], 
     datetime.datetime(2017, 10, 30, 19, 55, 20): ['this is an october tweet'],} 
>>> from itertools import groupby 
>>> for month, group in groupby(d.items(), lambda (k, v): k.month): 
...  print(month) 
...  for dt, tweet in group: 
...   print(dt, tweet) 
...   
10 
2017-10-30 19:55:20 ['this is an october tweet'] 
9 
2017-09-30 19:55:20 ['this is some tweet text'] 
2017-09-30 20:55:20 ['this is another tweet'] 
>>> 

Et bien sûr, vous pouvez l'imprimer dans un format plus agréable et ainsi de suite (jointure interne est nécessaire parce que chaque touche semble être une liste):

>>> for month, group in groupby(d.items(), lambda (k, v): k.month): 
...  tweets = list(group) 
...  print("%d tweet(s) in month %d" % (len(tweets), month)) 
...  print('\n'.join(','.join(tweet) for (dt, tweet) in tweets)) 
...  
1 tweet(s) in month 10 
this is an october tweet 
2 tweet(s) in month 9 
this is some tweet text 
this is another tweet 
>>> 
+0

Je vois à quel point groupby serait plus facile dans ce cas mais je continue à obtenir un 'SyntaxError' dans la première ligne de la boucle for, juste sous le '(k, v)'. J'utilise python 3. Cela ferait-il une différence puisque votre code ressemble à python 2? – e1v1s

+0

Ah oui, excuses, @ e1v1s change tout 'print x' en' print (x) '(Python 3 n'est pas installé sur cette machine). – Bahrom

+0

Oui, j'ai déjà ajouté les parenthèses autour des instructions d'impression. le 'Syntax Error' est mentionné dans le commentaire ci-dessus :) – e1v1s

0

Première chose: vous mettez deux éléments dans votre dict avec exactement la même clé. Le second écrasera le premier. Pour le reste, je vais supposer que le second élément de votre exemple est légèrement différent (seconds=21).

La raison pour laquelle votre code ne fonctionne pas comme prévu, c'est que vous décrémentez endDate et startDate dans votre boucle for. Par conséquent, vous vérifiez uniquement chaque date par rapport à un seul élément de la dict; si cet objet arrive à atterrir dans ce mois, il est imprimé. Sinon, ce n'est pas le cas. Pour illustrer, voici ce que vous obtenez si vous changez print-print(datetimeStart, datetimeEnd, k, v):

2017-09-01 00:00:00 2017-10-01 00:00:00 2017-09-30 19:55:20 ['this is some tweet text'] 
['this is some tweet text'] 
2017-08-01 00:00:00 2017-09-01 00:00:00 2017-09-30 19:55:21 ['this is another tweet'] 
2017-07-01 00:00:00 2017-08-01 00:00:00 2017-09-30 19:55:20 ['this is some tweet text'] 
2017-06-01 00:00:00 2017-07-01 00:00:00 2017-09-30 19:55:21 ['this is another tweet'] 
2017-05-01 00:00:00 2017-06-01 00:00:00 2017-09-30 19:55:20 ['this is some tweet text'] 
2017-04-01 00:00:00 2017-05-01 00:00:00 2017-09-30 19:55:21 ['this is another tweet'] 
2017-03-01 00:00:00 2017-04-01 00:00:00 2017-09-30 19:55:20 ['this is some tweet text'] 
2017-02-01 00:00:00 2017-03-01 00:00:00 2017-09-30 19:55:21 ['this is another tweet'] 
2017-01-01 00:00:00 2017-02-01 00:00:00 2017-09-30 19:55:20 ['this is some tweet text'] 

Le correctif avec le moindre changement à votre code existant serait de déplacer simplement les décréments en face de la boucle for et dedent le bloc if endDate... au niveau de la boucle while:

while start: 
    endDate-=1 
    startDate-=1 
    for k,v in tweetDict.items(): 
     datetimeStart = datetime(2017, startDate, 1) 
     datetimeEnd = datetime(2017,endDate, 1) 
     print(datetimeStart, datetimeEnd, k, v) 
     if datetimeStart < k < datetimeEnd: 
      print(v) 
    if endDate == 2: 
     start = False 
     break 

bien sûr, à ce moment-là, vous pourriez tout aussi bien se débarrasser du bloc if endDate... et faire while endDate > 2:.