4

Python version: 3.x

I have two dictionaries with same keys and the values are arrays. Most of the questions I saw here, for the required purpose, have only one value for each key. What I want is to merge those two dictionaries with values as joined array. Maybe below would clear:

What I've:

d1 = {(1, "Autumn"): np.array([2.5, 4.5, 7.5, 9.5]), (1, "Spring"): np.array([10.5, 11.7, 12.3, 15.0])}
d2 = {(1, "Autumn"): np.array([10.2, 13.3, 15.7, 18.8]), (1, "Spring"): np.array([15.6, 20, 23, 27])}

I've tried:

d3 = {**d1, **d2}

What I want:

d3 = {(1, "Autumn"): np.array([2.5, 4.5, 7.5, 9.5, 10.2, 13.3, 15.7, 18.8]), (1, "Spring"): np.array([10.5, 11.7, 12.3, 15.0, 15.6, 20, 23, 27])}

Am I missing something here? Please help!

P.S: I've looked at How to merge two dictionaries in a single expression?.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
PratikSharma
  • 321
  • 2
  • 17

4 Answers4

4

If you always have the same keys in both dicts, this should fit your needs:

d3 = {key:np.hstack([d1[key],d2[key]]) for key in d1.keys()}

Outputs:

In [7]: d3
Out[7]: 
{(1, 'Autumn'): array([ 2.5,  4.5,  7.5,  9.5, 10.2, 13.3, 15.7, 18.8]),
 (1, 'Spring'): array([10.5, 11.7, 12.3, 15. , 15.6, 20. , 23. , 27. ])}

But this relies on the assumption, that for every key there is a value and that every key appears in both dicts.

user8408080
  • 2,428
  • 1
  • 10
  • 19
  • Thanks! It also relies on array dimensions. `ValueError: all the input array dimensions except for the concatenation axis must match exactly`. Upvote, since most of the dictionaries I'm working on have same dimensions. – PratikSharma Jan 04 '19 at 16:53
2

I believe you need smth like:

{key:np.append(d1[key], d2[key]) for key in d1.keys()}

Not sure about np.append though. And, of course, it will work only if dicts have the same keys.

Myroslav Hryshyn
  • 716
  • 7
  • 18
2

Try this:

>>> import numpy as np
>>> d1 = {(1, "Autumn"): np.array([2.5, 4.5, 7.5, 9.5]), (1, "Spring"): np.array([10.5, 11.7, 12.3, 15.0])}
>>> d2 = {(1, "Autumn"): np.array([10.2, 13.3, 15.7, 18.8]), (1, "Spring"): np.array([15.6, 20, 23, 27])}
>>> d3 = {k: np.concatenate((d1.get(k, np.array([])), d2.get(k, np.array([])))) for k in set(d1.keys()).union(set(d2.keys()))}
>>> d3
{(1, 'Spring'): array([10.5, 11.7, 12.3, 15. , 15.6, 20. , 23. , 27. ]), (1, 'Autumn'): array([ 2.5,  4.5,  7.5,  9.5, 10.2, 13.3, 15.7, 18.8])}

Notes:

  • It's a dict comprehension
  • First, a union of the keys in the 2 dicts is computed, to make sure that no key is left aside (for that, the keys in each dict are converted into a set)
  • For each element in the above set, get the corresponding array (empty one if the key is not present) from each dict, and concatenate them
  • This is the Pythonic (and also general) approach, my numpy knowledge is somewhere close to 0 (I'm sure that it's pretty obvious from the code snippet - it looks awfully complex with all those parentheses), it's extremely likely that numpy has something to make things in a much more elegant manner
  • [SO]: How to merge two dictionaries in a single expression? desired output and the current one (considering that the dict values are simply iterables (whether they are Python or numpy or any other kind is irrelevant)) are 2 different (and equally correct) approaches of the merge concept regarding dicts, in case of common keys:
    • One only keeps the value from the last dict
    • The other sums (whatever sum would mean for the operands) all of them
CristiFati
  • 38,250
  • 9
  • 50
  • 87
1
import numpy as np

d1 = {(1, "Autumn"): [2.5, 4.5, 7.5, 9.5], (1, "Spring"): [10.5, 11.7, 12.3, 15.0]}
d2 = {(1, "Autumn"): [10.2, 13.3, 15.7, 18.8], (1, "Spring"): [15.6, 20, 23, 27]}
d3 = {(1, "Autumn"): np.array(d1[(1, "Autumn")] + d2[(1, "Autumn")]), (1,"Spring"): np.array(d1[(1, "Spring")] + d2[(1, "Spring")])}

I used the np.array() in the end because there is difference between lists and numpy arrays. When you use the A + B in numpy, each element of the A added to the array other element of the B. On the other hand, when use A+B where A and B are lists, they join each other.

Jacob Fuchs
  • 359
  • 1
  • 3
  • 14