0

Question:

I have a list of arrays such as:

a = [array([0, 4]), array([1, 3, 2])]

From another variable X, I want to take two subsets which are chosen by the index in each array in a.

X = [0.1, 0.7, 0.9, 0.2, 0.3] 

What I want to have is now:

result_1 = [0.1, 0.3]
result_2 = [0.7, 0.2, 0.9]

My solution would be to use a for loop such as:

def getresult(X, indices):
     result = []
     for i in indices:
          result.append(X[i])
     return result

This works fine:

getresult(X, a[0])
[0.1, 0.3]

My previous experience with programming suggest, that there is a much more beautiful and simple way to do so and that this is the place to ask. Preferably someone would know a solution that does not need looping.

Background/application:

Background: Crossvalidation for parameter optimization.

I have a list containing datapoints such as

X = [0.1, 0.7, 0.9, 0.2, 0.3]

Now I want to repeatedly take z samples out of that list (which actually is much bigger than this example). Therefore I create a new variable:

indices = np.arange(0,len(X),1)

HERE: [0, 1, 2, 3, 4]

Which then i shuffle and create nfold samples:

np.random.shuffle(indices)        
nfold_indices = np.array_split(indices,nfolds)

HERE with nfolds = 2: nfold_indices = [array([0, 4]), array([1, 3, 2])]
3
  • Are you sure that your solution is working with a[1]? Commented Jun 15, 2016 at 12:38
  • Just tested it again, yes it does work. Commented Jun 15, 2016 at 12:40
  • Indeed, sorry, I misread your code. Commented Jun 15, 2016 at 12:41

3 Answers 3

1

return [X[i] for i in indices] would work.

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

Comments

0

Use a list comprehension, with a default for safety, in case an index from a is not in X:

a = [array('i', [0, 4]), array('i', [1, 3, 2])]
X = [0.1, 0.7, 0.9, 0.2, 0.3] 

result = [[(X[i:]+[0])[0] for i in o] for o in a]
#                  ^ default
# [[0.1, 0.3], [0.7, 0.2, 0.9]]

So in the event you have an arbitrary array containing an out of range index:

a = [array('i', [0, 4]), array('i', [1, 3, 20])]
#                                           ^ out of range
result = [[(X[i:]+[0])[0] for i in o] for o in a]
# [[0.1, 0.3], [0.7, 0.2, 0]]
#                         ^

Your code does not break

5 Comments

Something I never liked... ask a list for the element 20, and it raises an IndexError, ask the list to give you elements 20 and forward and will return quietly an empty list...
Well, that functionality comes handy in cases like this.
I find: result = [[ X[i] if i < len(X) else 0 for i in o] for o in a] more readable in that case... Does not rely on people knowing that particular detail and also works if X is an array.
@Jblasco That won't work for i = -1. It returns 0 instead of the last element in the list.
Indeed, you are right... That's the problem one tries to go too compact and readable. Thanks for pointing it out.
0

My first attempt, which basically follows your way of doing things in a more compact way would be:

result1, result2 = [ [X[ii] for ii in array] for array in a]

If you can be bothered to convert X to a numpy array, you can do:

X = np.array([ 0.1,  0.7,  0.9,  0.2,  0.3])
result1, result2 = X[a[0]], X[a[1]]

But this has the problem that it does not generalise well for more than a few arrays within a. Even if some people will hate me for using a lambda, another compact way of doing it that generalises better is:

results = map(lambda x: X[x], a)

2 Comments

why would some hate anyone for using lambda ?
jejeje, there is a forever-ongoing religious war between people that love and people that hate lambdas. I'm quite indiferent, but see for example: lambda-the-ultimate.org/node/1298 Guido van Rossum himself had some things to say about lambdas.

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.