1

I know this has been asked dozens of times, and I've tried to get the intuition (here, here) of working with multi-dimensional arrays but I can't figure out the process.

I am getting days, weeks, months of the year using yeardatescalendar() from the Calendar library, packed into a 4D list.

import calendar

cal = calendar.Calendar()
yr_11 = cal.yeardatescalendar(2011)

The return value is a list of month rows. Each month row contains up to 3 months. Each month contains between 4 and 6 weeks and each week contains 1–7 days.

enter image description here

I am trying to convert this to a 2D array so it is just a list of weeks. But even when I'm trying to do this I don't understand the output.

# create an array
arr = np.array(yr_11)

arr.ndim # this returns '2'

arr.shape # this returns (4,3)

# yr_11 holds 63 weeks, so I tried to reshape
new_array = arr.reshape(63,1)

But it throws an error: ValueError: cannot reshape array of size 12 into shape (63,1)

Can someone please explain what's going on and help turn this into a 2D array?

Edit: essentially I'm looking for this

[[datetime.date(2010, 12, 27),
 datetime.date(2010, 12, 28),
 datetime.date(2010, 12, 29),
 datetime.date(2010, 12, 30),
 datetime.date(2010, 12, 31),
 datetime.date(2011, 1, 1),
 datetime.date(2011, 1, 2)],
[datetime.date(2011, 1, 3),
 datetime.date(2011, 1, 4),
 datetime.date(2011, 1, 5),
 datetime.date(2011, 1, 6),
 datetime.date(2011, 1, 7),
 datetime.date(2011, 1, 8),
 datetime.date(2011, 1, 9)], ... ]
Bn.F76
  • 783
  • 2
  • 12
  • 30

1 Answers1

1

The nested list returned by yeardatescalendar has the following hierarchy:

  • Multi-month chunks
  • Months
  • Weeks
  • Days

Therefore, for example, yr_11[2][1][3][2] will give the datetime representing the 3rd day in the 4th week of the 2nd month in the 3rd chunk. Remember that indexing goes from left (least nested) to right (most nested), but we normally read such elements in the opposite direction (most granular first)

To simplify our calculations, we can pass width=12 so that our result will consist of one chunk containing 12 months.

Next, it remains simply to flatten the list and pass the result to np.array:

import calendar

cal = calendar.Calendar()
yr_11 = cal.yeardatescalendar(2011, width=12)

flat = [day for month in yr_11[0] for week in month for day in week]
dates = np.array(flat)

print(dates)

Output:

[datetime.date(2010, 12, 27) datetime.date(2010, 12, 28)
 datetime.date(2010, 12, 29) datetime.date(2010, 12, 30)
 datetime.date(2010, 12, 31) datetime.date(2011, 1, 1)
 ...
 datetime.date(2011, 12, 28) datetime.date(2011, 12, 29)
 datetime.date(2011, 12, 30) datetime.date(2011, 12, 31)
 datetime.date(2012, 1, 1)]
gmds
  • 19,325
  • 4
  • 32
  • 58
  • I was having a _really_ hard time trying to understand this so thank you! I will accept your answer but I would need a list of weeks, as opposed to list of the dates. I threw in an edit so you can see what I mean. – Bn.F76 Apr 14 '19 at 04:48
  • @Bn.F76 `flat = [week for month in yr_11[0] for week in month]` will work if you want weeks. – gmds Apr 14 '19 at 04:49
  • @mgds This has been incredibly helpful!! One last thing, originally when I converted the list to array `arr`, and called `arr.ndim` , why did it return 2 if the dimension was 4. Similarly, why was `shape (4,2)` and `size 12` ? – Bn.F76 Apr 14 '19 at 04:58
  • @Bn.F76 Each dimension of an `np.array` must have the *same length*. However, clearly some months have more weeks than others, so `numpy` didn't expand the inner `lists` to arrays, but took them as single objects. – gmds Apr 14 '19 at 05:28