Frage

Ich habe eine Python-Liste mit einer Reihe von Einträgen, die ich brauche, entweder mit Downsampling:

  • Eine maximale Anzahl von Zeilen. Zum Beispiel Begrenzung eine Liste von 1234 Einträgen bis 1000.
  • Ein Teil der ursprünglichen Reihen. Zum Beispiel, so dass die Liste 1/3 seiner ursprünglichen Länge.

(Ich muss in der Lage, beide Möglichkeiten zu tun, sondern nur eine zu einem Zeitpunkt verwendet wird).

Ich glaube, dass für die maximale Anzahl von Zeilen kann ich nur den Anteil berechnen erforderlich und passieren, dass der proportionalen downsizer:

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

... so dass ich nur eine Downsampling-Funktion wirklich brauchen. Für Hinweise, bitte?

EDIT: Die Liste enthält Objekte, nicht numerische Werte so ich interpolieren nicht brauchen. Löschen von Objekten ist in Ordnung.

LÖSUNG:

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

Danke.

War es hilfreich?

Lösung

Halten Sie einen Zähler, der Sie durch den zweiten Wert erhöhen. Boden es jedes Mal, und ergibt den Wert an diesem Index.

Andere Tipps

Sie können islice von itertools verwenden:

from itertools import islice

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

Verbrauch:

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

Statt islice() + list() ist es effizienter zu nutzen slice Syntax direkt, wenn der Eingang ist bereits eine Sequenztyp:

def downsample_to_proportion(rows, proportion):
    return rows[::int(1 / proportion)]

Diese Lösung könnte ein bisschen übertrieben für das ursprüngliche Plakat, aber ich dachte, ich würde den Code teilen, dass ich dieses und ähnliche Probleme zu lösen, wurde unter Verwendung.

Es ist ein bisschen lange (ca. 90 Zeilen), aber wenn man oft diesen Bedarf hat, will einen einfach zu bedienende oneliner, und braucht eine puren-Python Abhängigkeit freie Umgebung dann rechne ich es von Nutzen sein könnte.

Grundsätzlich ist das einzige, was Sie tun müssen, ist Ihre Liste an die Funktion übergeben und es sagen, in welcher Länge Sie Ihre neue Liste sein wollen, und die Funktion wird entweder:

  • verkleinern Ihre Liste Elemente, wenn die neue Länge kleiner ist, ähnlich wie die früheren Antworten bereits vorgeschlagen, fallen zu lassen.
  • Strecke / gehobene Liste an (das Gegenteil von dem Downsizing), wenn die neue Länge größer ist, mit der zusätzlichen Option, dass Sie entscheiden können, ob sie:
    • linear bw Interpolations die bekannten Werte (automatisch gewählt, wenn die Liste ints oder Schwimmer enthält)
    • duplizieren jeden Wert, so dass sie eine proportionale Größe der neuen Liste (automatisch gewählt, wenn die Liste enthält nicht-Zahlen)
    • besetzen
    • ziehen die ursprünglichen Werte auseinander und lassen Lücken zwischen

Alles ist innerhalb einer Funktion gesammelt, so, wenn Sie es brauchen kopieren Sie einfach und fügen Sie sie in Ihr Skript und Sie beginnen können Sie es sofort.

Zum Beispiel könnte man sagen:

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

und get

[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]

Beachten Sie, dass kleinere Ungenauigkeiten aufgrund Gleitkomma-Einschränkungen auftreten. Auch ich schrieb dies für Python 2.x, so dass es zu verwenden, auf Python 3.x nur eine einzige Zeile hinzufügen, die sagen xrange = range.

Und hier ist ein raffinierter Trick zwischen positionierte Subitems in einer Liste von Listen zu interpolieren. So zum Beispiel können Sie leicht interpolieren zwischen RGB-Farb Tupeln einen Farbverlauf von x nr von Schritten erstellen. Unter der Annahme einer Liste von RGB-Farb Tupeln von 3 und eine gewünschte GRADIENTLENGTH Variable, die Sie tun dies mit:

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

Es könnte wahrscheinlich braucht durchaus ein paar Optimierungen, ich hatte ziemlich viel Experimentieren zu tun. Wenn Sie das Gefühl verbessern kann es fühlen sich frei, meine Post zu bearbeiten. Hier ist der Code:

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

Kann nicht random.choices () lösen Ihr Problem? Weitere Beispiele sind verfügbar hier

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top