Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Merge branch 'lix_setitem'

  • Loading branch information...
commit c17a1a7ffdfa397326e2ec85a3e8a6db34408b18 2 parents 3a68b19 + 3bc0147
kwgoodman authored
12 README.rst
Source Rendered
@@ -70,7 +70,7 @@ Install
70 70 Requirements:
71 71
72 72 ======================== ====================================================
73   -la Python, NumPy 1.5.1-1.6.1, Bottleneck 0.5.0
  73 +la Python, NumPy 1.5.1-1.6.2, Bottleneck 0.6.0
74 74 Unit tests nose
75 75 ======================== ====================================================
76 76
@@ -79,7 +79,7 @@ Optional:
79 79 ============================= ================================================
80 80 Archive larrys in HDF5 h5py, HDF 1.8
81 81 Compile for speed boost gcc or MinGW
82   -lar.ranking(norm='gaussian') SciPy 0.8.0, 0.9.0
  82 +lar.ranking(norm='gaussian') SciPy 0.8, 0.9, 0.10
83 83 ============================= ================================================
84 84
85 85 You can download the `latest version of la <http://pypi.python.org/pypi/la>`_
@@ -122,9 +122,9 @@ After you have installed ``la``, run the suite of unit tests::
122 122 >>> import la
123 123 >>> la.test()
124 124 <snip>
125   - Ran 3002 tests in 9.225s
  125 + Ran 3012 tests in 9.225s
126 126 OK
127   - <nose.result.TextTestResult run=3002 errors=0 failures=0>
  127 + <nose.result.TextTestResult run=3012 errors=0 failures=0>
128 128
129 129 The ``la`` package contains C extensions that speed up common alignment
130 130 operations such as adding two unaligned larrys. If the C extensions don't
@@ -135,8 +135,8 @@ Python functions::
135 135 >>> la.info()
136 136 la version 0.7.0
137 137 la file /usr/local/lib/python2.6/dist-packages/la/__init__.pyc
138   - NumPy 1.6.1
139   - Bottleneck 0.5.0
  138 + NumPy 1.6.2
  139 + Bottleneck 0.6.0
140 140 HDF5 archiving Available (h5py 2.0.0)
141 141 listmap Faster C version
142 142 listmap_fill Faster C version
5 RELEASE.rst
Source Rendered
@@ -21,6 +21,11 @@ la 0.7
21 21 - larry.merge() when update=True, larry.morph(), larry.morph_like()
22 22 - larry.take()
23 23 - larry.sortaxis()
  24 +- larry.nan_replace()
  25 +
  26 +**Enhancements**
  27 +
  28 +- Added setitem ability to label indexing (lix)
24 29
25 30 **Breakage from la 0.6**
26 31
97 la/deflarry.py
@@ -1926,7 +1926,7 @@ def lix(self):
1926 1926 array([1, 4])
1927 1927
1928 1928 """
1929   - return Getitemlabel(self)
  1929 + return Lix(self)
1930 1930
1931 1931 def __setitem__(self, index, value):
1932 1932 """
@@ -3918,8 +3918,8 @@ def nan_replace(self, replace_with=0):
3918 3918
3919 3919 """
3920 3920 y = self.copy()
3921   - np.putmask(y.x, np.isnan(y.x), replace_with)
3922   - return y
  3921 + bn.replace(y.x, np.nan, replace_with)
  3922 + return y
3923 3923
3924 3924 # Size, shape, type ------------------------------------------------------
3925 3925
@@ -4848,13 +4848,15 @@ def __repr__(self):
4848 4848
4849 4849 # Label indexing support functions for the lix method ------------------------
4850 4850
4851   -class Getitemlabel(object):
  4851 +class Lix(object):
4852 4852 "Utility class for the lix method."
4853 4853
4854 4854 def __init__(self2, self):
4855 4855 self2.lar = self
4856 4856
4857 4857 def __getitem__(self2, index):
  4858 + # Note: setitem uses the same (slightly modified) code
  4859 + # So if you update this code update setitem as well
4858 4860 y = self2.lar
4859 4861 if y.shape == (0,):
4860 4862 return self2.lar
@@ -4866,12 +4868,12 @@ def __getitem__(self2, index):
4866 4868 if typ == list:
4867 4869 # Example: lar.lix[['a', 'b', 'c']]
4868 4870 index2 = labels2indices(y.label[0], index)
4869   - if len(index) == 1:
  4871 + if len(index) == 1:
4870 4872 index2 = index2[0]
4871   - return y[index2]
  4873 + return y[index2]
4872 4874 elif typ == slice:
4873 4875 # Examples: lar.lix[['a']:], lar.lix[['a']:['b']],
4874   - # lar.lix[['a']:['b']:2], lar.lix[2:['b']]
  4876 + # lar.lix[['a']:['b']:2], lar.lix[2:['b']]
4875 4877 return y[slicemaker(index, y.labelindex, 0)]
4876 4878 elif typ == tuple:
4877 4879 index2 = []
@@ -4881,35 +4883,99 @@ def __getitem__(self2, index):
4881 4883 elif len(index) < y.ndim:
4882 4884 index3 = list(index) + [slice(None)] * (y.ndim - len(index))
4883 4885 else:
4884   - raise IndexError, 'Invalid index'
  4886 + raise IndexError, 'Invalid index'
4885 4887 for ax, idx in enumerate(index3):
4886 4888 typ = type(idx)
4887 4889 if typ == list:
4888 4890 idx2 = labels2indices(y.label[ax], idx)
4889   - if len(idx) > 1:
  4891 + if len(idx) > 1:
4890 4892 label.append(idx)
4891 4893 index2.append(idx2)
4892   - elif typ == slice:
  4894 + elif typ == slice:
4893 4895 s = slicemaker(idx, y.labelindex, ax)
4894 4896 slar = range(*s.indices(y.shape[ax]))
4895 4897 lab = y.label[ax][s]
4896 4898 if len(lab) > 1:
4897   - label.append(lab)
  4899 + label.append(lab)
4898 4900 index2.append(slar)
4899 4901 elif isscalar(idx):
4900   - index2.append([idx])
  4902 + index2.append([idx])
4901 4903 else:
4902 4904 raise IndexError, 'Unsupported indexing operation.'
4903 4905 x = np.squeeze(y.x[np.ix_(*index2)])
4904 4906 if x.ndim == 0:
4905 4907 return x[()]
4906 4908 else:
4907   - return larry(x, label)
  4909 + return larry(x, label)
4908 4910 elif isscalar(index):
4909 4911 # Example: lar.lix[0]
4910   - return y[index]
  4912 + return y[index]
4911 4913 else:
4912   - raise IndexError, 'Unsupported indexing operation.'
  4914 + raise IndexError, 'Unsupported indexing operation.'
  4915 +
  4916 + def __setitem__(self2, index, value):
  4917 + # Note: getitem uses the same (slightly modified) code
  4918 + # So if you update this code update getitem as well
  4919 + y = self2.lar
  4920 + if y.shape == (0,):
  4921 + raise IndexError('index out of bounds')
  4922 + elif 0 in y.shape:
  4923 + msg = 'lix does not support shapes that contain 0 '
  4924 + msg += 'such as (0,) and (2, 0 ,3).'
  4925 + raise ValueError, msg
  4926 + typ = type(index)
  4927 + if typ == list:
  4928 + # Example: lar.lix[['a', 'b', 'c']]
  4929 + index2 = labels2indices(y.label[0], index)
  4930 + if len(index) == 1:
  4931 + index2 = index2[0]
  4932 + y[index2] = value
  4933 + elif typ == slice:
  4934 + # Examples: lar.lix[['a']:], lar.lix[['a']:['b']],
  4935 + # lar.lix[['a']:['b']:2], lar.lix[2:['b']]
  4936 + y[slicemaker(index, y.labelindex, 0)] = value
  4937 + elif typ == tuple:
  4938 + index2 = []
  4939 + label = []
  4940 + if len(index) == y.ndim:
  4941 + index3 = index
  4942 + elif len(index) < y.ndim:
  4943 + index3 = list(index) + [slice(None)] * (y.ndim - len(index))
  4944 + else:
  4945 + raise IndexError, 'Invalid index'
  4946 + for ax, idx in enumerate(index3):
  4947 + typ = type(idx)
  4948 + if typ == list:
  4949 + idx2 = labels2indices(y.label[ax], idx)
  4950 + if len(idx) > 1:
  4951 + label.append(idx)
  4952 + index2.append(idx2)
  4953 + elif typ == slice:
  4954 + s = slicemaker(idx, y.labelindex, ax)
  4955 + slar = range(*s.indices(y.shape[ax]))
  4956 + lab = y.label[ax][s]
  4957 + if len(lab) > 1:
  4958 + label.append(lab)
  4959 + index2.append(slar)
  4960 + elif isscalar(idx):
  4961 + index2.append([idx])
  4962 + else:
  4963 + raise IndexError, 'Unsupported indexing operation.'
  4964 + if isinstance(value, larry):
  4965 + if value.ndim != len(index2):
  4966 + raise IndexError, '`value` has wrong ndim'
  4967 + for ax, ix2 in enumerate(index2):
  4968 + lab = [y.label[ax][i] for i in ix2]
  4969 + if lab != value.label[ax]:
  4970 + raise IndexError, 'larry labels are not aligned'
  4971 + y.x[np.ix_(*index2)] = value.x
  4972 + else:
  4973 + y.x[np.ix_(*index2)] = value
  4974 + elif isscalar(index):
  4975 + # Example: lar.lix[0]
  4976 + y[index] = value
  4977 + else:
  4978 + raise IndexError, 'Unsupported indexing operation.'
4913 4979
4914 4980 def slicemaker(index, labelindex, axis):
4915 4981 "Convert a slice that may contain labels to a slice with indices."
@@ -4944,4 +5010,3 @@ def labels2indices(label, labels):
4944 5010 except ValueError:
4945 5011 raise ValueError, 'Could not map label to index value.'
4946 5012 return indices
4947   -
85 la/tests/lix_test.py
... ... @@ -1,10 +1,14 @@
1 1 "Unit tests of larry's indexing by label method, lix"
2 2
  3 +from nose.tools import assert_raises
  4 +
3 5 import numpy as np
4 6 from numpy.testing import assert_equal
5 7
  8 +import la
6 9 from la import larry
7 10 from la.util.misc import isscalar
  11 +from la.util.testing import assert_larry_equal as ale
8 12
9 13 S = slice
10 14 N = None
@@ -106,11 +110,76 @@ def test_lix(si=si):
106 110 msg = '\nlix fail on shape %s and index %s\n'
107 111 yield assert_equal, actual, desired, msg % (str(shape), str(index))
108 112
109   -
110   -
111   -
112   -
113   -
114   -
115   -
116   -
  113 +# ---------------------------------------------------------------------------
  114 +# Test lix setitem
  115 +
  116 +def lix_setitem_test_01():
  117 + actual = la.lrange(label=[['a', 'b']])
  118 + actual.lix[['a']] = 9
  119 + desired = la.lrange(label=[['a', 'b']])
  120 + desired[0] = 9
  121 + ale(actual, desired)
  122 +
  123 +def lix_setitem_test_02():
  124 + actual = la.lrange(label=[['a', 'b'], ['c', 'd']])
  125 + actual.lix[['a']] = 9
  126 + desired = la.lrange(label=[['a', 'b'], ['c', 'd']])
  127 + desired[0] = 9
  128 + ale(actual, desired)
  129 +
  130 +def lix_setitem_test_03():
  131 + actual = la.lrange(label=[['a', 'b'], ['c', 'd']])
  132 + actual.lix[0] = 9
  133 + desired = la.lrange(label=[['a', 'b'], ['c', 'd']])
  134 + desired[0] = 9
  135 + ale(actual, desired)
  136 +
  137 +def lix_setitem_test_04():
  138 + actual = la.lrange(label=[['a', 'b'], ['c', 'd']])
  139 + actual.lix[['a']:['b']] = 9
  140 + desired = la.lrange(label=[['a', 'b'], ['c', 'd']])
  141 + desired[0:1] = 9
  142 + ale(actual, desired)
  143 +
  144 +def lix_setitem_test_05():
  145 + actual = la.lrange(label=[['a', 'b'], ['c', 'd']])
  146 + actual.lix[['b'], ['d']] = 9
  147 + desired = la.lrange(label=[['a', 'b'], ['c', 'd']])
  148 + desired[1, 1] = 9
  149 + ale(actual, desired)
  150 +
  151 +def lix_setitem_test_06():
  152 + actual = la.lrange(label=[['a', 'b', 'c'], ['1', '2', '3']])
  153 + actual.lix[['a', 'b'], ['1', '2']] = 9
  154 + desired = la.lrange(label=[['a', 'b', 'c'], ['1', '2', '3']])
  155 + desired[:2, :2] = 9
  156 + ale(actual, desired)
  157 +
  158 +def lix_setitem_test_07():
  159 + actual = la.lrange(label=[['a', 'b', 'c'], ['1', '2', '3']])
  160 + actual.lix[['a', 'b'], ['1', '2']] = np.arange(4).reshape(2, 2)
  161 + desired = la.lrange(label=[['a', 'b', 'c'], ['1', '2', '3']])
  162 + desired[:2, :2] = np.arange(4).reshape(2, 2)
  163 + ale(actual, desired)
  164 +
  165 +def lix_setitem_test_08():
  166 + actual = la.lrange(label=[['a', 'b'], ['c', 'd']])
  167 + actual.lix[['a']] = la.larry([9, 10], [['c', 'd']])
  168 + desired = la.lrange(label=[['a', 'b'], ['c', 'd']])
  169 + desired[0] = [9, 10]
  170 + ale(actual, desired)
  171 +
  172 +def lix_setitem_test_09():
  173 + def lixit(lar, index, value):
  174 + lar.lix[index] = value
  175 + actual = la.lrange(label=[['a', 'b'], ['c', 'd']])
  176 + index = ['a']
  177 + value = la.larry([10, 9], [['d', 'c']])
  178 + assert_raises(IndexError, lixit, actual, index, value)
  179 +
  180 +def lix_setitem_test_10():
  181 + actual = la.lrange(label=[['a', 'b'], ['c', 'd']])
  182 + actual.lix[:,['d']] = la.larry([[9], [10]], [['a', 'b'],['d']])
  183 + desired = la.lrange(label=[['a', 'b'], ['c', 'd']])
  184 + desired[:,-1] = [9, 10]
  185 + ale(actual, desired)

0 comments on commit c17a1a7

Please sign in to comment.
Something went wrong with that request. Please try again.