質問

多数のエントリを含む Python リストがあり、次のいずれかを使用してダウンサンプリングする必要があります。

  • 最大行数。たとえば、1234 エントリのリストを 1000 に制限します。
  • 元の行の割合。たとえば、リストを元の長さの 1/3 にします。

(両方の方法を実行できる必要がありますが、一度に使用できるのは 1 つだけです)。

最大行数については、必要な比率を計算し、それを比例ダウンサイザーに渡すだけでよいと思います。

def downsample_to_max(self, rows, max_rows):
        return downsample_to_proportion(rows, max_rows / float(len(rows)))

...つまり、実際に必要なダウンサンプリング関数は 1 つだけです。何かヒントはありますか?

編集: リストには数値ではなくオブジェクトが含まれているため、補間する必要はありません。物を落としても大丈夫です。

解決:

def downsample_to_proportion(self, rows, proportion):

    counter = 0.0
    last_counter = None
    results = []

    for row in rows:

        counter += proportion

        if int(counter) != last_counter:
            results.append(row)
            last_counter = int(counter)

    return results

ありがとう。

役に立ちましたか?

解決

あなたは第二の値によってインクリメントカウンタを、保管してください。床その都度、そのインデックスの値を得た。

他のヒント

あなたはisliceからitertoolsを使用することができます:

from itertools import islice

def downsample_to_proportion(rows, proportion=1):
    return list(islice(rows, 0, len(rows), int(1/proportion)))

使用方法:

x = range(1,10)
print downsample_to_proportion(x, 0.3)
# [1, 4, 7]

:入力がすでにシーケンス型の場合その代わりislice() + list()の直接スライス構文を使用する方が効率的です
def downsample_to_proportion(rows, proportion):
    return rows[::int(1 / proportion)]

この解決策は元の投稿者にとっては少しやりすぎかもしれませんが、この問題や同様の問題を解決するために私が使用してきたコードを共有したいと思いました。

少し長い (約 90 行) ですが、このようなニーズが頻繁にあり、使いやすいワンライナーが必要で、純粋な Python 依存関係のない環境が必要な場合には、役に立つかもしれないと思います。

基本的に、あなたがしなければならないことは、リストを関数に渡して、新しいリストの長さを伝えることだけです。そうすれば、関数は次のいずれかを実行します。

  • ダウンサイズ すでに提案されている以前の回答と同様に、新しい長さが小さい場合に項目をドロップすることでリストを作成します。
  • ストレッチ新しい長さが大きい場合は、リストを /upscale (ダウンサイズの逆) するかどうかを決定できるオプションが追加されます。
    • 既知の値を線形補間します (リストに int または float が含まれる場合は自動的に選択されます)
    • 新しいリストの比例したサイズを占めるように各値を複製します (リストに数値以外が含まれている場合は自動的に選択されます)
    • 元の値を引き離し、間にギャップを残す

すべてが 1 つの関数内に収集されるため、必要な場合はコピーしてスクリプトに貼り付けるだけで、すぐに使用を開始できます。

たとえば、次のように言うことができます。

origlist = [0,None,None,30,None,50,60,70,None,None,100]
resizedlist = ResizeList(testlist, 21)
print(resizedlist)

そして手に入れる

[0, 5.00000000001, 9.9999999999900009, 15.0, 20.000000000010001, 24.999999999989999, 30, 35.0, 40.0, 45.0, 50.0, 55.0, 60.0, 65.0, 70, 75.000000000010004, 79.999999999989996, 85.0, 90.000000000010004, 94.999999999989996, 100]

浮動小数点の制限により、若干の誤差が生じることに注意してください。また、これは Python 2.x 用に書いたものなので、Python 3.x で使用するには、次の 1 行を追加するだけです。 xrange = range.

ここでは、リストのリスト内で配置されたサブアイテム間を補間する気の利いたトリックを紹介します。したがって、たとえば、RGB カラー タプル間を簡単に補間して、x nr ステップのカラー グラデーションを作成できます。3 の RGB カラータプルのリストと必要な GRADIENTLENGTH 変数を想定して、これを次のように実行します。

crosssections = zip(*rgbtuples)
grad_crosssections = ( ResizeList(spectrum,GRADIENTLENGTH) for spectrum in crosssections )
rgb_gradient = [list(each) for each in zip(*grad_crosssections)]

おそらくかなりの最適化が必要になる可能性があり、かなりの実験を行う必要がありました。改善できると思われる場合は、お気軽に私の投稿を編集してください。コードは次のとおりです。

def ResizeList(rows, newlength, stretchmethod="not specified", gapvalue=None):
    """
    Resizes (up or down) and returns a new list of a given size, based on an input list.
    - rows: the input list, which can contain any type of value or item (except if using the interpolate stretchmethod which requires floats or ints only)
    - newlength: the new length of the output list (if this is the same as the input list then the original list will be returned immediately)
    - stretchmethod: if the list is being stretched, this decides how to do it. Valid values are:
      - 'interpolate'
        - linearly interpolate between the known values (automatically chosen if list contains ints or floats)
      - 'duplicate'
        - duplicate each value so they occupy a proportional size of the new list (automatically chosen if the list contains non-numbers)
      - 'spread'
        - drags the original values apart and leaves gaps as defined by the gapvalue option
    - gapvalue: a value that will be used as gaps to fill in between the original values when using the 'spread' stretchmethod
    """
    #return input as is if no difference in length
    if newlength == len(rows):
        return rows
    #set auto stretchmode
    if stretchmethod == "not specified":
        if isinstance(rows[0], (int,float)):
            stretchmethod = "interpolate"
        else:
            stretchmethod = "duplicate"
    #reduce newlength 
    newlength -= 1
    #assign first value
    outlist = [rows[0]]
    writinggapsflag = False
    if rows[1] == gapvalue:
        writinggapsflag = True
    relspreadindexgen = (index/float(len(rows)-1) for index in xrange(1,len(rows))) #warning a little hacky by skipping first index cus is assigned auto
    relspreadindex = next(relspreadindexgen)
    spreadflag = False
    gapcount = 0
    for outlistindex in xrange(1, newlength):
        #relative positions
        rel = outlistindex/float(newlength)
        relindex = (len(rows)-1) * rel
        basenr,decimals = str(relindex).split(".")
        relbwindex = float("0."+decimals)
        #determine equivalent value
        if stretchmethod=="interpolate":
            #test for gap
            maybecurrelval = rows[int(relindex)]
            maybenextrelval = rows[int(relindex)+1]
            if maybecurrelval == gapvalue:
                #found gapvalue, so skipping and waiting for valid value to interpolate and add to outlist
                gapcount += 1
                continue
            #test whether to interpolate for previous gaps
            if gapcount > 0:
                #found a valid value after skipping gapvalues so this is where it interpolates all of them from last valid value to this one
                startvalue = outlist[-1]
                endindex = int(relindex)
                endvalue = rows[endindex]
                gapstointerpolate = gapcount 
                allinterpolatedgaps = Resize([startvalue,endvalue],gapstointerpolate+3)
                outlist.extend(allinterpolatedgaps[1:-1])
                gapcount = 0
                writinggapsflag = False
            #interpolate value
            currelval = rows[int(relindex)]
            lookahead = 1
            nextrelval = rows[int(relindex)+lookahead]
            if nextrelval == gapvalue:
                if writinggapsflag:
                    continue
                relbwval = currelval
                writinggapsflag = True
            else:
                relbwval = currelval + (nextrelval - currelval) * relbwindex #basenr pluss interindex percent interpolation of diff to next item
        elif stretchmethod=="duplicate":
            relbwval = rows[int(round(relindex))] #no interpolation possible, so just copy each time
        elif stretchmethod=="spread":
            if rel >= relspreadindex:
                spreadindex = int(len(rows)*relspreadindex)
                relbwval = rows[spreadindex] #spread values further apart so as to leave gaps in between
                relspreadindex = next(relspreadindexgen)
            else:
                relbwval = gapvalue
        #assign each value
        outlist.append(relbwval)
    #assign last value
    if gapcount > 0:
        #this last value also has to interpolate for previous gaps       
        startvalue = outlist[-1]
        endvalue = rows[-1]
        gapstointerpolate = gapcount 
        allinterpolatedgaps = Resize([startvalue,endvalue],gapstointerpolate+3)
        outlist.extend(allinterpolatedgaps[1:-1])
        outlist.append(rows[-1])
        gapcount = 0
        writinggapsflag = False
    else:
        outlist.append(rows[-1])
    return outlist

()あなたの問題を解決random.choicesことができませんか? より多くの例が用意されていここ

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top