2

I can create a normal matrix with numpy using

np.zeros([800, 200])

How can I create a matrix with a negative index - as in a 1600x200 matrix with row index from -800 to 800?

1
  • 9
    That's not how a matrix works. Negative indexes usually refer to a position relative to the end. Commented Nov 27, 2018 at 7:31

8 Answers 8

3
+250

Not sure what you need it for but maybe you could use a dictionary instead.

a={i:0 for i in range(-800,801)}

With this you can call a[-800] to a[800].

For 2-D,

a={(i,j):0 for i in range(-800,801) for j in range(-100,101)}

This can be called with a[(-800,-100)] to a[(800,100)]

Sign up to request clarification or add additional context in comments.

2 Comments

Except for explicit looping, where the usage may be similar to a NumPy array, a dict will not be nearly as versatile as a NumPy array. Since NumPy arrays do support negative indices, it is not clear what the advantage of using dict would be.
One huge drawback is that you cannot slice a dictionary in any way.
3

Not clear what is being asked. NumPy arrays do already support access via negative indexing, which will reach out to positions relative to the end, e.g.:

import numpy as np


m = np.arange(3 * 4).reshape((3, 4))
print(m)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

print(m[-1, :])
# [ 8  9 10 11]

print(m[:, -1]
# [ 3  7 11]

If you need an array that is contiguous near the zero of your indices, one option would be to write a function to map each indices i to i + d // 2 (d being the size along the given axis), e.g.:

def idx2neg(indexing, shape):
    new_indexing = []
    for idx, dim in zip(indexing, shape):
        if isinstance(idx, int):
            new_indexing.append(idx + dim // 2)
        ...
        # not implemented for slices, boolean masks, etc.
    return tuple(new_indexing)

Note that the above function is not as flexible as what NumPy accepts, it is just meant to give some idea on how to proceed.

Comments

2

Probably you refer to the Fortran-like arbitrary indexing of arrays. This is not compatible with Python. Check the comments in this question. Basically it clashes with Python way of treating negative indexes, which is to start counting from the end (or right) of the array.

Comments

2

I don't know why you would need that but if you just need it for indexing try following function:

def getVal(matrix, i, k):
    return matrix[i + 800][k]

This function only interpretes the first index so you can type in an index from -800 up to 799 for a 1600x200 matrix.

If you want to index relatively to its number of lines try following function:

def getVal(matrix, i, k):
    return matrix[i + len(matrix) // 2][k]

Hope that helps!

Comments

1

Extending the dependency list, this is kind of straightforward using a pandas DataFrame with custom index.

However you will need to change slightly the syntax for how you access rows (and columns), yet there is the possibility to slice multiple rows and columns.

This is specific to 2d numpy arrays:

import numpy as np
import pandas as pd

a = np.arange(1600*200).reshape([1600, 200])
df = pd.DataFrame(a, index=range(-800, 800))

Once you have such dataframe you can access columns and rows (with few syntax inconsistencies):

  • Access the 1st column: df[0]
  • Access the 1st row: df.loc[-800]
  • Access rows from 1st to 100th: df.loc[-800:-700] and df[-800: -700]
  • Access columns from 1st to 100th: df.loc[:, 0:100]
  • Access rows and columns: df.loc[-800:-700, 0:100]

Full documentation on pandas slicing and indexing can be found here.

2 Comments

Perhaps worth mentioning that this approach would only work for 2D arrays, and for columns (2nd dimension) you would need to "index" the columns with the columns property/keyword, e.g. df = pd.DataFrame(a, index=range(-800, 800), columns=range(-100, 100))
I mentioned that this works only for 2d numpy arrays. It didn't come to mind to specify one can do the same on columns, as OP asked to index rows. But you are correct, you have the freedom to access columns with negative indexes as well
0

You can use the np.arange function to generate an array of integers from -800 to 800, and then reshape this array into the desired shape using the reshape method.

Here's an example of how you could do this:

import numpy as np

# Create an array of integers from -800 to 800
indices = np.arange(-800, 801)

# Reshape the array into a 1600 x 200 matrix
matrix = indices.reshape(1600, 200)

This will create a 1600 x 200 matrix with row indices ranging from -800 to 800. You can then access elements of the matrix using these negative indices just like you would with positive indices.

For example, to access the element at row -1 and column 0, you could use the following code:

matrix[-1, 0]

Comments

0

You can create a matrix with a negative index using the following code:

import numpy as np

my_matrix = np.zeros((1600, 200))
my_matrix = np.pad(my_matrix, ((800, 800), (0, 0)), mode='constant', constant_values=0)
my_matrix = my_matrix[-800:800, :]

Comments

0

You can create numpy.ndarray subclass. Take a look at the below example, it can create an array with a specific starting index.

import numpy as np

class CustomArray(np.ndarray):
    def __new__(cls, input_array, startIndex=None):
        obj = np.asarray(input_array)
        if startIndex is not None:
            if isinstance(startIndex, int):
                startIndex = (startIndex, )
            else:
                startIndex = tuple(startIndex)
            assert len(startIndex), len(obj.shape[0])

        obj = obj.view(cls)
        obj.startIndex = startIndex
        return obj

    def __array_finalize__(self, obj):
        if obj is None: return
        self.startIndex = getattr(obj, 'startIndex', None)
    
    @staticmethod
    def adj_index(idx, adj):
        if isinstance(idx, tuple):
            if not isinstance(adj, tuple):
                adj = tuple([adj for i in range(len(idx))])
            idx = tuple([CustomArray.adj_index(idx_i, adj_i) for idx_i, adj_i in zip(idx, adj)])
        elif isinstance(idx, slice):
            if isinstance(adj, tuple):
                adj = adj[0]
            idx = slice(idx.start-adj if idx.start is not None else idx.start, 
                        idx.stop-adj if idx.stop is not None else idx.stop, 
                        idx.step)
        else:
            if isinstance(adj, tuple):
                adj = adj[0]
            idx = idx - adj
        return idx
    
    def __iter__(self):
        return np.asarray(self).__iter__()

    
    def __getitem__(self, idx):
        if self.startIndex is not None:
            idx = self.adj_index(idx, self.startIndex)
        return np.asarray(self).__getitem__(idx)
    
    def __setitem__(self, idx, val):
        if self.startIndex is not None:
            idx = self.adj_index(idx, self.startIndex)
        return np.asarray(self).__setitem__(idx, val)
    
    def __repr__(self):
        r = np.asarray(self).__repr__()
        if self.startIndex is not None:
            r += f'\n StartIndex: {self.startIndex}'
        return r

Example

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.