1
Tool = [[0 for x in xrange(3)] for y in xrange(len(xTool)-1)]
for l in xrange((len(xTool) - 1)):
  Tool[l][0] = yTool[l]; Tool[l][1] = xTool[l]; Tool[l][2] = zTool[l]  

I am starting with points coordinates, which are in 3 lists (xTool, yTool, zTool), representing respectively the x, y and z coordinates of all my points.

The aim here is to create a matrix of 3 columns and many rows (over 10,000), where each row represent the point's 3 coordinates. The next step I do is a vector transformation like so: (This has minor importance, only if you really want to understand what i'm doing

rTool = numpy.zeros_like(Tool)   
for rt in xrange((len(xTool) - 1)):
  rTool[rt][0] = (Tool[rt][0] * cos(angle)) - (Tool[rt][1] * sin(angle))
  rTool[rt][1] = (Tool[rt][0] * sin(angle)) + (Tool[rt][1] * cos(angle))
  rTool[rt][2] = Tool[rt][2]

Finally, what I'm trying to do is order my rTool in regards to my 2nd column ([1]). For instance, I printed 5 entries of my rTool. By sorting them according to the 2nd column, the last row should be the first. I am really struggling to do this, and I suspect it's because I have tuples instead of a real 3 column mathematical matrix.

[[ -584.89837646 -3648.6472168    402.177948  ]
 [ -542.8659668  -3663.34545898   405.76959229]
 [ -500.831604   -3678.04785156   409.32122803]
 [ -458.79336548 -3692.75854492   412.7930603 ]
 [ -416.74984741 -3637.48022461   416.15090942]]

Don't hesitate to ask for clarification and I hope you will be able to help me! Thanks.

Julien
  • 35
  • 1
  • 5
  • similar question asked 5 years ago http://stackoverflow.com/questions/613183/sort-a-python-dictionary-by-value – taotao.li Sep 23 '14 at 10:32
  • You might want to use tuples for your coordinates, so you would have a list of triples `[(x, y, z,)(x, y, z)]`. Tuples are immutable, but faster. – data Sep 23 '14 at 10:48

3 Answers3

2

First and foremost, learn numpy. Doing this kind of thing in plain python goes against everything pythonic.

Once you've done that:

sorted_rtool = rTool[np.argsort(rTool[:,1])]

To drive the importance of numpy home:

rTool = np.dot(Tool, R)

Is not only a lot cleaner, its also orders of magnitude faster.

Eelco Hoogendoorn
  • 10,459
  • 1
  • 44
  • 42
  • Why is it going *against everything pythonic* ? – will Sep 23 '14 at 10:30
  • 'Everything' is a big word, but its simply the wrong tool for the job in every way imaginable. Reinventing things like matrix multiplication in python is a bad case of reinventing the wheel for starters. Furthermore it obscures the intent of your code, it is much more bug-prone, and performance is guaranteed to suffer by orders of magnitude. – Eelco Hoogendoorn Sep 23 '14 at 10:34
  • I would say that's often true, but i really don't like the way that `numpy` reuses `np.dot()` for matrix multiplication, and sum products as well as just the dot product. I would argue that that is unpythonic, as it obsucres what's actually happening. If you're going to say "use numpy because you can make it more pythonic and not reinvent the wheel", then you should reccomend using the `matrix` class, and then you just need to do `M * N` to achieve what you want. Which i would argue is more pythonic that `np.dot(M,N)` – will Sep 23 '14 at 10:41
  • If Eelco ever has the nerve to recommend using the `matrix` class, I hope he is ready for the downvote storm... ;-) Seriously, numpy's `matrix` class is a constant source of pain, and is best avoided. Wait a year or so, and with numpy 1.10 and Python 3.5 you can do `M @ N`, see [PEP 465](http://legacy.python.org/dev/peps/pep-0465/). – Jaime Sep 23 '14 at 13:56
  • Well, I think I have been the most vocal critic of the proposed @ operator, and I feel its only a notch better than using the matrix class, so you wont see me recommending either ;). Personally, I use einsum for pretty much all linear products, because I don't like having to keep track of conventions as to which axes goes where. Explicit is better than implicit. How does dot obscure what is actually happening? Though it does not make axes explicit, it is a whole lot more explicit than a multiplication operator, which could mean a dozen different things when applied to an array. – Eelco Hoogendoorn Sep 23 '14 at 21:07
0

You could use the 'key' parameter of 'sort' or 'sorted', see https://wiki.python.org/moin/HowTo/Sorting#Key_Functions

In your case:

rTool.sort(key=lambda x: x[1])

or

rToolSorted = sorted(rTool, key=lambda x: x[1])
Martin
  • 1
  • 1
0

You're looking for the key keyword of list.sort() (or the builtin sorted()) Look at the Key Functions section here.

Often people just use a lambda function for the sort key, as it's concise, and you often don't use the sort function more than once. All it is, is a function which returns an object key, on which each element of the list is sorted.

So you could do:

def keyFunc(element):
  return element[1]

rTool.sort(key=keyFunc)

or:

rTool.sort(key=lambda x: x[1])

In both cases, you could use rTool = sorted(rTool, key=...) instead, the difference being that list.sort() does an inplace sort, and is more efficient if you don't need the original array.

The key function can really be anything you want, provided it returns something else that can be sorted, so if your points were objects with x, y, z attributes, then you could do rTool.sort(key x: x.y)

will
  • 10,260
  • 6
  • 46
  • 69