1

I have a dictionary WO of the format:

WO = {datetime: {'V1', 'V2', 'V3', 'V4'}}

Where datetime is the key of the (example) format:

datetime.date(2014, 6, 20)

And V1 through V4 are lists containing floating values.

Example:

WO = {datetime.date(2014, 12, 20): {'V1': [11, 15, 19], 
                                    'V2': [12, 3, 4], 
                                    'V3': [50, 55, 56], 
                                    'V4': [100, 112, 45]},
      datetime.date(2014, 12, 21): {'V1': [10, 12, 9], 
                                    'V2': [16, 13, 40], 
                                    'V3': [150, 155, 156], 
                                    'V4': [1100, 1132, 457]},
      datetime.date(2014, 12, 22): {'V1': [107, 172, 79], 
                                    'V2': [124, 43, 44], 
                                    'V3': [503, 552, 561], 
                                    'V4': [1000, 1128, 457]}}

If I want to aggregate values in V1 through to V4 according to the week for a given date, for example:

my_date = datetime.date(2014, 5, 23)

For this given date, aggregate all values in V1 through to V4 for this week, where the week starts from Monday.

year, week, weekday = datetime.date(my_date).isocalendar()

This line gives me the week and weekday for this particular date.

If I have a function as:

def week(date):
    '''
    date is in 'datetime.date(year, month, date)' format

    This function is supposed to aggregate values in 'V1', 'V2', 'V3' and 
    'V4' for a whole week according to the parameter 'date'
    '''

How should I proceed next to define such a function?

Georgy
  • 12,464
  • 7
  • 65
  • 73
Arun
  • 2,222
  • 7
  • 43
  • 78
  • I see. What have you tried to do to solve this problem yourself? Stack Overflow isn't really meant to be a code-writing service. Give it your best shot, then come here when you have a specific implementation problem. Check out the How to Ask section of the SO guide here: https://stackoverflow.com/help/how-to-ask – Jordan Singer Jan 31 '19 at 14:15
  • How will that "aggregation" work actually? What will be the result for the provided example? – Georgy Jan 31 '19 at 14:25

3 Answers3

1

from what i understood you want to do some manipulation over all V1...V4 values of given week of a given date. first i'll start with finding the monday (week start) of the given date.

year, week, weekday = my_date.isocalendar()     
last_monday_date = my_date - datetime.timedelta(days = weekday - 1)

would give you the last monday date.

then you can use this for a date range over the week days: Creating a range of dates in Python

and lastly in the daterange for loop iterate over WO values and get your resualt.

Omer Ben Haim
  • 595
  • 4
  • 14
0

If I add the missing braces to WO to get rid of the syntax errors (which you should really have checked before posting):

WO = {datetime.date(2014, 12, 20): {'V1': [11, 15, 19], 'V2': [12, 3, 4], 'V3': [50, 55, 56], 'V4': [100, 112, 45]}, datetime.date(2014, 12, 22): {'V1': [107, 172, 79], 'V2': [124, 43, 44], 'V3': [503, 552, 561], 'V4': [1000, 1128, 457]}, datetime.date(2014, 12, 21): {'V1': [10, 12, 9], 'V2': [16, 13, 40], 'V3': [150, 155, 156], 'V4': [1100, 1132, 457]}}

I can then do this to see what week numbers are in the data:

>>> for date, values in WO.items():
        year, week, _ = date.isocalendar()
        print (date,year,week)

and I can see that in this sample there are two weeks you want to aggregate:

2014-12-20 2014 51
2014-12-22 2014 52
2014-12-21 2014 51

That is, your data relates to ISO weeks 51 and 52 of 2014. You are consolidating by week, so your aggregated data will have a key (year, week) but without the day. (You need the year because there could be different years in your data.) So you are looking to build a dict with the keys (2014, 51) and (2014, 52). One will have 3 values associated with "V1"-"V4" because there is only one day in that week and there is nothing to consolidate. The other week will have 6 values associated with "V1"-"V4" because there are two days for that week in the data.

Start with an empty dict to contain the summary:

>>> summary = {}

Loop through the dates to find the years and week numbers as before, but this time gather the data according to the (year, week) keys:

>>> for date, values in WO.items():
      year, week, _ = date.isocalendar()
      if (year, week) not in summary:
        summary [(year, week)] = {vn: [] for vn in values} # empty lists for vn = 'V1' - 'V4'
      for vn in values:
        summary[(year, week)][vn].extend(values[vn])

>>> summary
{(2014, 51): {'V1': [11, 15, 19, 10, 12, 9], 'V2': [12, 3, 4, 16, 13, 40], 'V3': [50, 55, 56, 150, 155, 156], 'V4': [100, 112, 45, 1100, 1132, 457]}, (2014, 52): {'V1': [107, 172, 79], 'V2': [124, 43, 44], 'V3': [503, 552, 561], 'V4': [1000, 1128, 457]}}
BoarGules
  • 16,440
  • 2
  • 27
  • 44
0

You can use a nested defaultdict to collect data from the same week, using the week number as key (or some other hashable identifier). Then use a nested dictionary comprehension to sum your list of lists elementwise.

from collections import defaultdict

dd = defaultdict(lambda: defaultdict(list))

for k1, v1 in WO.items():
    for k2, v2 in v1.items():
        dd[k1.isocalendar()[1]][k2].append(v2)

WO_agg = {k1: {k2: list(map(sum, zip(*v2))) for k2, v2 in v1.items()} \
          for k1, v1 in dd.items()}

print(WO_agg)
# {51: {'V1': [21, 27, 28],
#       'V2': [28, 16, 44],
#       'V3': [200, 210, 212],
#       'V4': [1200, 1244, 502]},
#  52: {'V1': [107, 172, 79],
#       'V2': [124, 43, 44],
#       'V3': [503, 552, 561],
#       'V4': [1000, 1128, 457]}}
jpp
  • 159,742
  • 34
  • 281
  • 339