5

これが他の場所で回答されている場合はお詫びします。検索してみましたが、私の質問に答えるものが見つかりませんでした(または、おそらく私は持っていますが、理解できませんでした)...

私はPython(v2.6.2)にかなり慣れておらず、浮動小数点値を含むリストのリストがあります。これは次のようになります(ただし、リストごとに200万以上のエントリがあります)。

cat = [[152.123, 150.456, 151.789, ...], [4.123, 3.456, 1.789, ...], [20.123, 22.456, 21.789, ...]]

ここで、3番目のリストの要素の昇順で、3つのリストすべてを並べ替えて、次のようにします。

cat_sorted = [[152.123, 151.789, 150.456, ...], [4.123, 1.789, 3.456, ...], [20.123, 21.789, 22.456, ...]]

私はいくつかのことを試しましたが、それらは私が探しているものを私に与えません(またはおそらく私はそれらを間違って使用しています)。私が探していることを行う方法はありますか?もしそうなら、最も簡単で最も速いものは何ですか(私が3 x 200万のエントリを持っていることを考えると)?別のリストを使用して1つのリストを並べ替える方法はありますか?

4

6 に答える 6

8

これは苦痛になりますが、デフォルトのPythonを使用すると、次の2つのオプションがあります。

  • 1番目と2番目のリストをで装飾enumerate()し、インデックスを使用してこれらを並べ替えて、3番目のリストの値を参照します。

    cat_sorted = [
        [e for i, e in sorted(enumerate(cat[0]), key=lambda p: cat[2][p[0]])],
        [e for i, e in sorted(enumerate(cat[1]), key=lambda p: cat[2][p[0]])],
        sorted(cat[2])
    ]
    

    ;cat[2]を使用する代わりに、インプレースでソートすると役立つ場合があります。sorted()他の2つを使用して回避することはできませんsorted()

  • zip()3つのリストを一緒に並べてから、この新しいリストのリストの3番目の要素で並べ替えてzip()から、元の構造に戻します。

    from operator import itemgetter
    cat_sorted = zip(*sorted(zip(*cat), key=itemgetter(2)))
    

何百万もの数の単純なPythonリストではなく、どちらもパフォーマンスバスターにはなりません。

于 2013-01-04T17:28:20.863 に答える
4

追加のライブラリを使用する場合は、PythonPandasをお勧めします。Rと同様のDataFrameオブジェクトがありdata.frame、コンストラクターでリストのリストを受け入れます。これにより、3列のデータ配列が作成されます。pandas.DataFrame.sort次に、組み込み関数を使用して、3番目の列(昇順または降順)で並べ替えることができます。

これを行うための単純なPythonの方法はたくさんありますが、問題の大きさを考えると、Pandasで最適化された関数を使用する方が良いアプローチです。また、ソートされたデータから何らかの種類の集計統計が必要な場合、Pandasはこれを簡単に実行できます。

于 2013-01-04T17:29:40.173 に答える
2

私が取る一般的なアプローチは、全体に対してシュワルツ変換を行うことでした。

3つのリストをまとめてタプルのリストに圧縮します。

3番目の要素をキーとして使用してタプルを並べ替えます。

新しくソートされたタプルのリストを繰り返し、3つのリストに再度入力します。

于 2013-01-04T17:30:01.060 に答える
1

完成させるために、numpyを使用したソリューション:

import numpy as np

cat = [[152.123, 150.456, 151.789],
        [4.123, 3.456, 1.789],
        [20.123, 22.456, 21.789]]

cat = np.array(cat) 
cat_sorted = cat[:, cat[2].argsort()]

print cat_sorted
[[ 152.123  151.789  150.456]
 [   4.123    1.789    3.456]
 [  20.123   21.789   22.456]]
于 2013-01-04T17:49:28.120 に答える
0

MartijnPietersとpcalcaoによる素晴らしい回答に基づいてそれを行う別の方法があります

def sort_by_last(ll):
    """
        >>> sort_by_last([[10, 20, 30], [3, 2, 1]])
        [[30, 20, 10], [1, 2, 3]]

        >>> sort_by_last([[10, 20, 30], [40, 50, 60], [3, 2, 1]])
        [[30, 20, 10], [60, 50, 40], [1, 2, 3]]

        >>> sort_by_last([[10, 20, 30], [40, 50, 60], [1, 1, 1]])
        [[10, 20, 30], [40, 50, 60], [1, 1, 1]]

        >>> sort_by_last([[10, 20, 30], [40, 50, 60], [1, 3, 1]])
        [[10, 30, 20], [40, 60, 50], [1, 1, 3]]

        >>> sort_by_last([[152.123, 150.456, 151.789], [4.123, 3.456, 1.789], [20.123, 22.456, 21.789]])
        [[152.123, 151.789, 150.456], [4.123, 1.789, 3.456], [20.123, 21.789, 22.456]]
    """
    return [sorted(x, key=lambda y: ll[-1][x.index(y)]) for x in ll]

大きな文字列にはdoctestを含むdocstringがあり、関数をテストするためにファイルにコピーして実行します。 python -m doctest -v <file>

于 2013-01-04T17:52:42.603 に答える
0

ここに、keysインデックスのソートされたリストがあります。

keys = sorted(range(len(cat[2])), key=cat[2].__getitem__)
cat_sorted = [[cat[i][k] for k in keys] for i in range(3)]
于 2013-01-04T20:50:25.050 に答える