From b910de42d50cfad6a827f02e5ed6bdb3b32296ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20de=20Menten?= Date: Fri, 9 Aug 2019 12:44:08 +0200 Subject: [PATCH] fixed X.axis_name[groups] when groups have the same axis name (closes #787) i.e. when the operation was not actually needed --- doc/source/changes/version_0_31.rst.inc | 25 +----- larray/core/axis.py | 5 +- larray/tests/test_axis.py | 102 +++++++++++++++++++++++- 3 files changed, 107 insertions(+), 25 deletions(-) diff --git a/doc/source/changes/version_0_31.rst.inc b/doc/source/changes/version_0_31.rst.inc index 5838bad17..40678df75 100644 --- a/doc/source/changes/version_0_31.rst.inc +++ b/doc/source/changes/version_0_31.rst.inc @@ -1,20 +1,6 @@ .. py:currentmodule:: larray -Syntax changes -^^^^^^^^^^^^^^ - -* renamed ``LArray.old_method_name()`` to :py:obj:`LArray.new_method_name()` (closes :issue:`1`). - -* renamed ``old_argument_name`` argument of :py:obj:`LArray.method_name()` to ``new_argument_name``. - - -Backward incompatible changes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -* other backward incompatible changes - - New features ^^^^^^^^^^^^ @@ -22,14 +8,6 @@ New features Excel file at once (closes :issue:`676`). -.. _misc: - -Miscellaneous improvements -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -* improved the performance of a few LArray methods. - - Fixes ^^^^^ @@ -39,3 +17,6 @@ Fixes * fixed taking a subset of an array with boolean labels for an axis if the user explicitly specify the axis (closes :issue:`735`). When the user does not specify the axis, it currently fails but it is unclear what to do in that case (see :issue:`794`). + +* fixed a regression in 0.30: X.axis_name[groups] failed when groups were originally defined on axes with the same name + (i.e. when the operation was not actually needed). Closes :issue:`787`. diff --git a/larray/core/axis.py b/larray/core/axis.py index f05b844dd..0c11f0997 100644 --- a/larray/core/axis.py +++ b/larray/core/axis.py @@ -758,7 +758,10 @@ def isscalar(k): list_res = [self[k] for k in key] return list_res if isinstance(key, list) else tuple(list_res) # allow targeting a label from an aggregated axis with the group which created it - elif (isinstance(key, Group) and isinstance(key.axis, Axis) and key.axis.name == self.name and + elif (not isinstance(self, AxisReference) and + isinstance(key, Group) and + isinstance(key.axis, Axis) and + key.axis.name == self.name and key.name in self): return LGroup(key.name, None, self) # elif isinstance(key, basestring) and key in self: diff --git a/larray/tests/test_axis.py b/larray/tests/test_axis.py index 1410e9e26..1204308ed 100644 --- a/larray/tests/test_axis.py +++ b/larray/tests/test_axis.py @@ -6,7 +6,8 @@ import numpy as np from larray.tests.common import assert_array_equal, assert_nparray_equal -from larray import Axis, LGroup, IGroup, read_hdf +from larray import Axis, LGroup, IGroup, read_hdf, X +from larray.core.axis import AxisReference def test_init(): @@ -98,7 +99,7 @@ def test_translate(): def test_getitem_lgroup_keys(): def group_equal(g1, g2): - return (g1.key == g2.key and g1.name == g2.name and g1.axis is g2.axis) + return g1.key == g2.key and g1.name == g2.name and g1.axis is g2.axis age = Axis(range(100), 'age') ages = [1, 5, 9] @@ -119,93 +120,125 @@ def group_equal(g1, g2): def test_getitem_group_keys(): a = Axis('a=a0..a2') alt_a = Axis('a=a1..a3') + key = a['a1'] + g = a[key] assert g.key == 'a1' assert g.axis is a + g = alt_a[key] assert g.key == 'a1' assert g.axis is alt_a + key = a['a1':'a2'] + g = a[key] assert g.key == slice('a1', 'a2') assert g.axis is a + g = alt_a[key] assert g.key == slice('a1', 'a2') assert g.axis is alt_a + key = a[['a1', 'a2']] + g = a[key] assert g.key == ['a1', 'a2'] assert g.axis is a + g = alt_a[key] assert g.key == ['a1', 'a2'] assert g.axis is alt_a + key = a.i[1] + g = a[key] assert isinstance(g, LGroup) assert g.key == 'a1' assert g.axis is a + g = alt_a[key] assert isinstance(g, LGroup) assert g.key == 'a1' assert g.axis is alt_a + key = a.i[1:3] + g = a[key] assert isinstance(g, LGroup) assert g.key == slice('a1', 'a2') assert g.axis is a + g = alt_a[key] assert isinstance(g, LGroup) assert g.key == slice('a1', 'a2') assert g.axis is alt_a + key = a.i[[1, 2]] + g = a[key] assert isinstance(g, LGroup) assert list(g.key) == ['a1', 'a2'] assert g.axis is a + g = alt_a[key] assert isinstance(g, LGroup) assert list(g.key) == ['a1', 'a2'] assert g.axis is alt_a + lg_a1 = a['a1'] lg_a2 = a['a2'] + g = a[lg_a1:lg_a2] assert isinstance(g, LGroup) assert g.key == slice('a1', 'a2') assert g.axis is a + g = alt_a[lg_a1:lg_a2] assert isinstance(g, LGroup) assert g.key == slice('a1', 'a2') assert g.axis is alt_a + pg_a1 = a.i[1] pg_a2 = a.i[2] + g = a[pg_a1:pg_a2] assert isinstance(g, LGroup) assert g.key == slice('a1', 'a2') assert g.axis is a + g = alt_a[pg_a1:pg_a2] assert isinstance(g, LGroup) assert g.key == slice('a1', 'a2') assert g.axis is alt_a + key = [a['a1'], a['a2']] + g = a[key] assert isinstance(g, LGroup) assert g.key == ['a1', 'a2'] assert g.axis is a + g = alt_a[key] assert isinstance(g, LGroup) assert g.key == ['a1', 'a2'] assert g.axis is alt_a + key = [a.i[1], a.i[2]] + g = a[key] assert isinstance(g, LGroup) assert g.key == ['a1', 'a2'] assert g.axis is a + g = alt_a[key] assert isinstance(g, LGroup) assert g.key == ['a1', 'a2'] assert g.axis is alt_a + key = [a['a1', 'a2'], a['a2', 'a1']] + g = a[key] assert isinstance(g, list) assert isinstance(g[0], LGroup) @@ -214,6 +247,7 @@ def test_getitem_group_keys(): assert g[1].key == ['a2', 'a1'] assert g[0].axis is a assert g[1].axis is a + g = alt_a[key] assert isinstance(g, list) assert isinstance(g[0], LGroup) @@ -222,7 +256,9 @@ def test_getitem_group_keys(): assert g[1].key == ['a2', 'a1'] assert g[0].axis is alt_a assert g[1].axis is alt_a + key = (a.i[1, 2], a.i[2, 1]) + g = a[key] assert isinstance(g, tuple) assert isinstance(g[0], LGroup) @@ -231,6 +267,7 @@ def test_getitem_group_keys(): assert list(g[1].key) == ['a2', 'a1'] assert g[0].axis is a assert g[1].axis is a + g = alt_a[key] assert isinstance(g, tuple) assert isinstance(g[0], LGroup) @@ -239,25 +276,33 @@ def test_getitem_group_keys(): assert list(g[1].key) == ['a2', 'a1'] assert g[0].axis is alt_a assert g[1].axis is alt_a + key = (a['a1'], a['a2']) + g = a[key] assert isinstance(g, LGroup) assert g.key == ['a1', 'a2'] assert g.axis is a + g = alt_a[key] assert isinstance(g, LGroup) assert g.key == ['a1', 'a2'] assert g.axis is alt_a + key = (a.i[1], a.i[2]) + g = a[key] assert isinstance(g, LGroup) assert g.key == ['a1', 'a2'] assert g.axis is a + g = alt_a[key] assert isinstance(g, LGroup) assert g.key == ['a1', 'a2'] assert g.axis is alt_a + key = (a['a1', 'a2'], a['a2', 'a1']) + g = a[key] assert isinstance(g, tuple) assert isinstance(g[0], LGroup) @@ -266,6 +311,7 @@ def test_getitem_group_keys(): assert g[1].key == ['a2', 'a1'] assert g[0].axis is a assert g[1].axis is a + g = alt_a[key] assert isinstance(g, tuple) assert isinstance(g[0], LGroup) @@ -274,7 +320,9 @@ def test_getitem_group_keys(): assert g[1].key == ['a2', 'a1'] assert g[0].axis is alt_a assert g[1].axis is alt_a + key = (a.i[1, 2], a.i[2, 1]) + g = a[key] assert isinstance(g, tuple) assert isinstance(g[0], LGroup) @@ -283,6 +331,7 @@ def test_getitem_group_keys(): assert list(g[1].key) == ['a2', 'a1'] assert g[0].axis is a assert g[1].axis is a + g = alt_a[key] assert isinstance(g, tuple) assert isinstance(g[0], LGroup) @@ -293,6 +342,55 @@ def test_getitem_group_keys(): assert g[1].axis is alt_a +def test_axis_ref_getitem_group_keys(): + # test that we can retarget a key to another axis using an axis ref + + # a) when the name of the axis is different + axis1 = Axis('axis1=a0..a2') + + g = X.axis2[axis1['a1']] + assert isinstance(g.key, str) and g.key == 'a1' + assert isinstance(g.axis, AxisReference) + assert g.axis.name == 'axis2' + + g = X.axis2[axis1['a1'], axis1['a2']] + assert isinstance(g.key, list) and g.key == ['a1', 'a2'] + assert isinstance(g.axis, AxisReference) + assert g.axis.name == 'axis2' + + g = X.axis2[[axis1['a1'], axis1['a2']]] + assert isinstance(g.key, list) and g.key == ['a1', 'a2'] + assert isinstance(g.axis, AxisReference) + assert g.axis.name == 'axis2' + + g = X.axis2[axis1['a1':'a2']] + assert isinstance(g.key, slice) and g.key == slice('a1', 'a2') + assert isinstance(g.axis, AxisReference) + assert g.axis.name == 'axis2' + + # b) when the name of the axis is the same (i.e. when the retarget is useless) + # this is what issue #787 was all about + g = X.axis1[axis1['a1']] + assert isinstance(g.key, str) and g.key == 'a1' + assert isinstance(g.axis, AxisReference) + assert g.axis.name == 'axis1' + + g = X.axis1[axis1['a1'], axis1['a2']] + assert isinstance(g.key, list) and g.key == ['a1', 'a2'] + assert isinstance(g.axis, AxisReference) + assert g.axis.name == 'axis1' + + g = X.axis1[[axis1['a1'], axis1['a2']]] + assert isinstance(g.key, list) and g.key == ['a1', 'a2'] + assert isinstance(g.axis, AxisReference) + assert g.axis.name == 'axis1' + + g = X.axis1[axis1['a1':'a2']] + assert isinstance(g.key, slice) and g.key == slice('a1', 'a2') + assert isinstance(g.axis, AxisReference) + assert g.axis.name == 'axis1' + + def test_init_from_group(): code = Axis('code=C01..C03') code_group = code[:'C02']