-2

I have a matrix like: [[ 4 5 6 ] [ 1 2 3 ] [ 7 8 9 ]]

and need the mean value of every row (5, 2, 8). The problem comes when I need to sort by the mean value of every row and print it alongside with original index of the row whose mean value I'm printing.

The output should first show the index and then the mean value like this: [2:2, 1:5, 3:8]

So far I have this without any idea how to ad index to it...

average = []

for i in range(m):
    k = numpy.mean(A[i])
    average.append(k)
average.sort()
print(average)
martineau
  • 119,623
  • 25
  • 170
  • 301
noname
  • 3
  • 2
  • https://stackoverflow.com/questions/6618515/sorting-list-based-on-values-from-another-list – sshashank124 Jan 04 '20 at 18:42
  • Instead of creating an array of mean values, create an array of pairs of (mean,inded). After, you can use a strategy similar to this https://stackoverflow.com/questions/37487406/how-to-use-a-custom-predicate-sort-with-python – jman Jan 04 '20 at 18:43
  • It's really helpful on Stackoverflow to communicate using the actual syntax of the language. This is not valid python: `[2:2, 1:5, 3:8]` so nobody really knows what you are trying to achieve in the end. Does that represent a list of strings? a nested list? A dictionary? – Mark Jan 04 '20 at 19:02

3 Answers3

1

Since you are using numpy, you should be avoiding explicit loops. There is no reason to loop over the list and call np.mean() on each element, when you can just use:

average = m.mean(axis=1)

to do it all at once.

You can then stack on the indices with one of the various stack utilities:

stacked = np.stack((np.indices(average.shape).reshape(-1),average), axis=-1)

This will give you a stacked array like:

array([[0., 5.],
       [1., 2.],
       [2., 8.]])

With that you can use argsort() to sort on the second element:

import numpy as np

m = np.array([[ 4, 5 ,6 ], [ 1, 2, 3 ], [ 7, 8, 9 ]])    
average = m.mean(axis=1)
stacked = np.stack((np.indices(average.shape).reshape(-1),average), axis=-1)
stacked[stacked[:, 1].argsort()]

result:

array([[1., 2.],
       [0., 5.],
       [2., 8.]])

With that you should be able to create the final output you want.

Mark
  • 90,562
  • 7
  • 108
  • 148
  • Sorry for not explaining the problem better, just started python a few days ago... Thank you for the help anyway! – noname Jan 04 '20 at 21:20
0

That can be achieved with sorted() and a lambda. Look:

Python 3.7.5 (default, Dec 15 2019, 17:54:26) 
[GCC 9.2.1 20190827 (Red Hat 9.2.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> a = [[4, 5, 6], [1, 2, 3], [7, 8, 9]] 
>>> sorted(a, key=lambda x: sum(x)/len(x))
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> 

Or, if you really want the averages sorted:

>>> sorted([sum(_)/len(_) for _ in a])
[2.0, 5.0, 8.0]
>>> 

To have the row index in a and its average, you do:

>>> sorted([(i, sum(v)/len(v)) for i,v in enumerate(a)], key=lambda x: x[1])
[(1, 2.0), (0, 5.0), (2, 8.0)]
>>> 

Finally, to have the row and its average, sorted by average, you just need to do:

>>> sorted([(_, sum(_)/len(_)) for _ in a], key=lambda x: x[1])
[([1, 2, 3], 2.0), ([4, 5, 6], 5.0), ([7, 8, 9], 8.0)]
>>> 
accdias
  • 5,160
  • 3
  • 19
  • 31
0

you can do it just:

import numpy
m = [[ 4, 5, 6 ] ,[ 1, 2, 3 ], [ 7, 8, 9 ]]

result = []
for idx,val in enumerate(m, 1):
    result.append((idx, int(numpy.mean(val))))

result_sorted = sorted(result, key=lambda x: x[1])
print (dict(result_sorted))

output:

{2: 2, 1: 5, 3: 8}

ncica
  • 7,015
  • 1
  • 15
  • 37