{"action":"created","issue":{"url":"https://api.github.com/repos/pydata/pandas/issues/5645","labels_url":"https://api.github.com/repos/pydata/pandas/issues/5645/labels{/name}","comments_url":"https://api.github.com/repos/pydata/pandas/issues/5645/comments","events_url":"https://api.github.com/repos/pydata/pandas/issues/5645/events","html_url":"https://github.com/pydata/pandas/issues/5645","id":23758915,"number":5645,"title":"Binary operations don't broadcast across multiindex","user":{"login":"roblevy","id":4764631,"avatar_url":"https://avatars.githubusercontent.com/u/4764631?v=3","gravatar_id":"","url":"https://api.github.com/users/roblevy","html_url":"https://github.com/roblevy","followers_url":"https://api.github.com/users/roblevy/followers","following_url":"https://api.github.com/users/roblevy/following{/other_user}","gists_url":"https://api.github.com/users/roblevy/gists{/gist_id}","starred_url":"https://api.github.com/users/roblevy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/roblevy/subscriptions","organizations_url":"https://api.github.com/users/roblevy/orgs","repos_url":"https://api.github.com/users/roblevy/repos","events_url":"https://api.github.com/users/roblevy/events{/privacy}","received_events_url":"https://api.github.com/users/roblevy/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/pydata/pandas/labels/API%20Design","name":"API Design","color":"AD7FA8"},{"url":"https://api.github.com/repos/pydata/pandas/labels/Enhancement","name":"Enhancement","color":"4E9A06"},{"url":"https://api.github.com/repos/pydata/pandas/labels/MultiIndex","name":"MultiIndex","color":"207de5"},{"url":"https://api.github.com/repos/pydata/pandas/labels/Numeric","name":"Numeric","color":"006b75"},{"url":"https://api.github.com/repos/pydata/pandas/labels/Reshaping","name":"Reshaping","color":"02d7e1"}],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/pydata/pandas/milestones/32","html_url":"https://github.com/pydata/pandas/milestones/Next%20Major%20Release","labels_url":"https://api.github.com/repos/pydata/pandas/milestones/32/labels","id":933188,"number":32,"title":"Next Major Release","description":"after 0.16.1 of course","creator":{"login":"jreback","id":953992,"avatar_url":"https://avatars.githubusercontent.com/u/953992?v=3","gravatar_id":"","url":"https://api.github.com/users/jreback","html_url":"https://github.com/jreback","followers_url":"https://api.github.com/users/jreback/followers","following_url":"https://api.github.com/users/jreback/following{/other_user}","gists_url":"https://api.github.com/users/jreback/gists{/gist_id}","starred_url":"https://api.github.com/users/jreback/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jreback/subscriptions","organizations_url":"https://api.github.com/users/jreback/orgs","repos_url":"https://api.github.com/users/jreback/repos","events_url":"https://api.github.com/users/jreback/events{/privacy}","received_events_url":"https://api.github.com/users/jreback/received_events","type":"User","site_admin":false},"open_issues":795,"closed_issues":52,"state":"open","created_at":"2015-01-13T10:53:19Z","updated_at":"2015-07-06T11:14:13Z","due_on":"2015-08-31T04:00:00Z","closed_at":null},"comments":13,"created_at":"2013-12-05T00:47:00Z","updated_at":"2015-07-06T14:52:12Z","closed_at":null,"body":"related #6360\r\n\r\nBased on [this SO question](http://stackoverflow.com/questions/20383972/binary-operation-broadcasting-across-multiindex?noredirect=1#comment30444368_20383972)\r\n\r\nConsider the following two Series:\r\n```python\r\nx = pd.DataFrame({'year':[1,1,1,1,2,2,2,2],\r\n                  'country':['A','A','B','B','A','A','B','B'],\r\n                  'prod':[1,2,1,2,1,2,1,2],\r\n                  'val':[10,20,15,25,20,30,25,35]})\r\nx = x.set_index(['year','country','prod']).squeeze()\r\n\r\ny = pd.DataFrame({'year':[1,1,2,2],'prod':[1,2,1,2],\r\n                  'mul':[10,0.1,20,0.2]})\r\ny = y.set_index(['year','prod']).squeeze()\r\n```\r\nwhich look like:\r\n```python\r\n    year  country  prod\r\n    1     A        1       10\r\n                   2       20\r\n          B        1       15\r\n                   2       25\r\n    2     A        1       20\r\n                   2       30\r\n          B        1       25\r\n                   2       35\r\n\r\nyear  prod\r\n1     1       10.0\r\n      2        0.1\r\n2     1       20.0\r\n      2        0.2\r\n```\r\nI find it to be an *extremely* common task, to perform binary operations by distributing the values of `y` over a particular level of `x`. For example, I'd like to multiply all values of product 1 in year 1 by 10.0, regardless of `country`.\r\n\r\nThe required result is therefore as follows:\r\n```python\r\n    year  country  prod\r\n    1     A        1       100.0\r\n                   2       2.0\r\n          B        1       150.0\r\n                   2       2.5\r\n    2     A        1       400.0\r\n                   2       6.0\r\n          B        1       500.0\r\n                   2       7.0\r\n```\r\n\r\nThe binary operation .mul() doesn't work as expected:\r\n```python\r\n>>> x.mul(y, level=['year','prod'])\r\nTraceback (most recent call last):\r\n  File \"<stdin>\", line 1, in <module>\r\n  File \"/usr/local/lib/python2.7/dist-packages/pandas/core/series.py\", line 334, in f\r\n    return self._binop(other, op, level=level, fill_value=fill_value)\r\n  File \"/usr/local/lib/python2.7/dist-packages/pandas/core/series.py\", line 2075, in _binop\r\n    this, other = self.align(other, level=level, join='outer')\r\n  File \"/usr/local/lib/python2.7/dist-packages/pandas/core/series.py\", line 2570, in align\r\n    return_indexers=True)\r\n  File \"/usr/local/lib/python2.7/dist-packages/pandas/core/index.py\", line 954, in join\r\n    return_indexers=return_indexers)\r\n  File \"/usr/local/lib/python2.7/dist-packages/pandas/core/index.py\", line 1058, in _join_level\r\n    raise Exception('Join on level between two MultiIndex objects '\r\nException: Join on level between two MultiIndex objects is ambiguous\r\n```\r\nTo create the required result, the user currently has to do this:\r\n```python\r\nx = x.reset_index('country').sort_index()\r\nx.val = x.val * y\r\nx = x.reset_index().set_index(['year',\r\n                               'country',\r\n                               'prod']).sortlevel()\r\n```"},"comment":{"url":"https://api.github.com/repos/pydata/pandas/issues/comments/118879106","html_url":"https://github.com/pydata/pandas/issues/5645#issuecomment-118879106","issue_url":"https://api.github.com/repos/pydata/pandas/issues/5645","id":118879106,"user":{"login":"roblevy","id":4764631,"avatar_url":"https://avatars.githubusercontent.com/u/4764631?v=3","gravatar_id":"","url":"https://api.github.com/users/roblevy","html_url":"https://github.com/roblevy","followers_url":"https://api.github.com/users/roblevy/followers","following_url":"https://api.github.com/users/roblevy/following{/other_user}","gists_url":"https://api.github.com/users/roblevy/gists{/gist_id}","starred_url":"https://api.github.com/users/roblevy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/roblevy/subscriptions","organizations_url":"https://api.github.com/users/roblevy/orgs","repos_url":"https://api.github.com/users/roblevy/repos","events_url":"https://api.github.com/users/roblevy/events{/privacy}","received_events_url":"https://api.github.com/users/roblevy/received_events","type":"User","site_admin":false},"created_at":"2015-07-06T14:52:12Z","updated_at":"2015-07-06T14:52:12Z","body":"This may or may not be relevant, but I've found a comparatively neat workaround for this problem: `unstack` the index level(s) which doesn't (don't) appear in the other `Series`.\r\n\r\n    In [81]: x.unstack('country').mul(y, axis=0).stack()\r\n    Out[81]: \r\n    year  prod  country\r\n    1     1     A          100.0\r\n                B          150.0\r\n          2     A            2.0\r\n                B            2.5\r\n    2     1     A          400.0\r\n                B          500.0\r\n          2     A            6.0\r\n                B            7.0\r\n    dtype: float64\r\n\r\nThis is not the best possible solution since it changes the order of the index of `x` which is unexpected, but it should be pretty efficient."}}