3

長さの異なる N 個の大きなリストがあり、リスト内の各値は長さ 25 の固定ウィンドウでのシグナルを表します。つまり、25 秒/ベース/などごとにシグナルの平均値を取得し、その値をリスト。

これは、さまざまな時間の長さ (すべて 25 btw の倍数) で実行されるさまざまな実験/デバイスに対して行います。

つまり、リスト 1 は 1000 回の実行で、リスト 1 の値は 1000/25=40、リスト 2 は 1025 分の実行、リスト 2 の値は 1025/25 = 41、リスト 3 は 2525 分の実行、2525/25 = 101 です。 list3 の値など...

ここで、比較のために、各リストを同じ数のビン (40 ビンとしましょう) に再スケーリングしたいと思います。

実際のところ、list1resized の長さは 40 になり、1000/40 = 25 であるため、その値は変更されません。list2resized は 41 値の長さから 40 値の長さになり、list3 は 101 値の長さから 40 値の長さになります (つまり、すべてのリストが同じサイズになりました)。

そしてここで質問です。適切なビンの加重平均を取得して、各リストのサイズを 40 の固定長に変更するにはどうすればよいですか?

例は質問を明確にします。

list1 = [4.8, 6.9, ...]  #40 values for the 1000 run
list2 = [5.6, 7.8, 8.9, 13.4, ...] #41 values for the 1025 run
list3 = [4.1, 5.6, 10.3, 9.8, 40, 30, 21.4, 3, 2,...] #101 values for the 2525 run

これで、サイズ変更されたリストは次のようになります。

list1resized = [4.8*25/25, 6.9*25/25,...] #40 values for the 1000 run
list2resized = [(5.6*25+7.8*0.625)/25.625, (7.8*24.375+8.9*1.275)/25.625, (23.725*8.9+1.9*13.4)/25.625,...] # 40 values, averaged accordingly, for the 1025 run
list3resized = [(4.1*25+5.6*25+10.3*13.125)/(63.125), (10.3*11.875+9.8*25+40*25+30*1.25)/(63.125),...] # 40 values, averaged accordingly, for the 2525 run

サイズ変更されたリストの各要素のこのような平均値を取得するために、サイズ変更された新しいビンの加重平均を取りました (つまり、list1 では 1000/40=25 の平均、list2 では 1025/40=25.625 の平均、list2 の平均はlist3 では 2525/40=63.125 など)。つまり、同じですが、加重平均に使用した式を使用します。

list1resized = [4.8*25/25, 6.9*25/25,...] #40 values for the 1000 run
list2resized = [(5.6*25+7.8*0.625)/25.625, (7.8*24.375+8.9*(25.65-24.375))/(25.625), (23.725*8.9+(25.625-23.725)*13.4)/(25.625),...] # 40 values, averaged accordingly, for the 1025 run
list3resized = [(4.1*25+5.6*25+10.3*13.125)/(63.125), (10.3*(25-13.125)+9.8*25+40*25+30*(63.125-25*3+13.125)))/(63.125),...] # 40 values, averaged accordingly, for the 2525 run

ご覧のとおり、面倒で扱いにくいものになる可能性がありますが、私は問題に対するpythonicでエレガントで迅速な解決策を探しています。

多くのリストに対してこれを何度も行う必要があるため、実行時間を考慮すると便利です。

アイデアがあるかどうかはわかりませんが、助けていただければ幸いです。

ありがとう。

4

3 に答える 3

3

このファンキーな[多分]ソリューションはどうですか?

最初に測定値のリスト...

l = [5.6, 7.8, 8.9, 13.4]

各測定値を25回コピーします(1秒に1回...)

l1 = [item for sublist in [list(itertools.repeat(k,25)) for k in l] for item in sublist]

1秒ごとに正規化します。

l2 = map(lambda x: x / 25., l1)

リストをn個のほぼ等しいパーティションにスライスする関数(以下にコピー)については、このSOの投稿を参照してください。

Python:リストをn個のほぼ等しい長さのパーティションにスライスする

def partition(lst, n):
    division = len(lst) / float(n)
    return [ lst[int(round(division * i)): int(round(division * (i + 1)))] for i in xrange(n) ]

リストの新しい長さを定義する

new_len = 2

1秒あたりのリストを、必要なセクションの数に分割します。

l3 = partition(l2, new_len)

各パーティションの1秒ごとの値を合計します

l4 = map(sum, l3)

リストのサイズの違いを正規化する

l5 = map(lambda x: x * new_len / float(len(l)), l4)

結果を賞賛する:

print l5
于 2012-10-16T20:18:13.800 に答える
3

これはかなり難しい問題ですが、実際よりも複雑にしていると思います。いくつかの観察から始めます。

観察 1. 関連するコーディングを減らすために、後まで多くのことを考慮に入れることができます。25 で除算して乗算する (実際の複素数をすばやく取得する) 代わりに、その操作を最後まで保存します。

list2resized = [i/25.625 for i in [(5.6*25+7.8*0.625), 
                                   (7.8*24.375+8.9*(25.65-24.375)), 
                                   (23.725*8.9+(25.625-23.725)*13.4),...]]

# consider using ratios, rather than division
list2resized = [i * 1.025 for i in [(5.6 * 1 + 7.8 * .025), 
                                    (7.8 * .975 + 8.9 * .050), 
                                    (8.9 * .95 + 13.4 * .075),...]]

観察 2. したがって、進行するすべての項の係数は 25 ずつ増加します。後書きまで 1000 による除算を保存します。選択した場合は、方程式全体に 1000 を掛けて、モジュラス演算子を使用できます...

 list2resized = [i * 1025/1000 for i in [(5.6 * 1000 + 7.8 * 25), # 1025 steps in
                                          (7.8 * 975 + 8.9 * 50), # 2050 steps in
                                          (8.9 * 950 + 13.4 * 75) # 3075 steps in

観察 3.

最終的なサイズ変更で必要な各「ビン」の長さは 1.025 である必要があります (41 個の開始ビンが与えられますが、最終的には調整するリストの長さに依存します)。 1.0 * list[0] + .025 * list[1] 観測 2 を考慮すると、方程式全体を級数として書き直すことができます--

# the sum of the coefficients is always equal to the resize ratio
(1 * n1) + (.025 * n2)
(.975 * n2) + (.050 * n3) 
(.950 * n3) + (.075 * n4)
...

これで、これらの係数を生成できます--

a = [i/40.0 for i in range(0, 40)][1:]
b = [1 - i/40.0 for i in range(0, 40)]

しかし、「回転」がそれ自体に追いつかないため、これらは簡単です。あなたがしなければならないのは、方程式のそれぞれの部分ごとに各ビンの係数を反復処理し、それらをまとめて圧縮し、それらを合計することだけです。これは、リストを元のサイズの半分まで最大限に圧縮するだけです。これが当てはまる場合、上記のアルゴリズムを使用する必要があります。これは、数値のリストを作成し、リスト内包表記を乗算するだけなので、他のどのアルゴリズムよりもはるかに高速です。

しかし、複雑なケースは、101 個の数字があり、複数の用語 (場合によっては 4 つ目も!) が現れる例です...

101/40.0 = 2.525 
# your bins need to be 2.525 units long.  

data = [4.1, 5.6, 10.3, 9.8, 40, 30, 21.4, 3, 2,...]

# calculated by hand
(1 * n1) + (1 * n2) + (.525 * n3) 
(.475 * n3) + (1 * n4) + (1 * n5) + (.05 * n6)
(.95 * n6) + (1 * n7) + (.575 * n8)
(.425 * n8) + (1 * n9) + (1 * n10) + (.100 * n11)

そのため、係数を生成するためのより良い方法が必要です。前述の (3) のように、最終項の 1 つの係数の合計は、新しい項目に対する古い項目の比率です。

101:40 = 2.525:1
41:40 = 1.025:1

次に係数の生成です。サブリストがなくなるまで反復する list-in-list データ構造を使用します。

[(1, 1, .525), (.475, 1, 1, .05) ...]

最初のサブリストは、新しいリストの項目 1 にマップされます。2 番目のサブリストから項目 2 まで、というように最後まで続きます。すべてのサブリストのすべての項目の合計は、元のリストの項目 n (この場合は 101) と等しくなければなりません。

実際に仕事をしなければならないので、先に進んでこれを投稿します。後で戻ってきて、それに取り組むようにします。

/編集

これは係数を生成する関数です。

n = 1000
d = 2525
items = 101
def coefficients(n, d, items):
    start = [n for i in xrange(items)]
    result = []
    p = []
    while True:
        while sum(p) < d:
            try:
                p.append(start.pop())
            except IndexError:
                return result
        extra = sum(p) % d
        p[-1] = n - extra
        result.append(p)
        p = [extra]

係数を繰り返し処理して、最終的な 40 個のリストを返します。さらにサポートが必要な場合はお知らせください。

于 2012-10-16T21:23:51.147 に答える
2

私はまだPythonにかなり慣れていないので、これをpythonicity、エレガンス、およびスピードで評価するには、他の誰かが必要です.

class StretchableList(list):
    def stretch(self, newlen):
        old = [ (i * (newlen-1), self[i]) for i in range(len(self)) ]
        new = [ i * (len(self)-1) for i in range(newlen) ]
        self[:] = []
        for n in new:
            while len(old) > 1 and n >= old[1][0]:
                old.pop(0)
            if old[0][0] == n:
                self.append(old[0][1])
            else:
                self.append( old[0][1] + \
                             float((n-old[0][0]))/(old[1][0]-old[0][0]) * \
                             (old[1][1]-old[0][1]) )
        return self

list基本的に、これは というメソッドを追加するだけの のサブクラスを定義しstretchます。目的の新しい長さで呼び出すと、新しい長さに引き伸ばされたり圧縮されたりします。私は加重平均をあなたとは少し異なって実行しました...同等である場合とそうでない場合がありますが、必要に応じて変更できる数学部分を想定しています.

于 2012-10-16T19:41:36.590 に答える