2016-03-19 7 views
2

Ich versuche, jeden Wert in einem Datenrahmen zwischen 0,01 und 0,99Python Pandas Dataframe: Daten zwischen 0,01 und 0,99 normalisieren?

Ich habe normalisiert erfolgreich verpflichtet, die Daten zwischen 0 und 1: .apply(lambda x: (x - x.min())/(x.max() - x.min())) wie folgt:

df = pd.DataFrame({'one' : ['AAL', 'AAL', 'AAPL', 'AAPL'], 'two' : [1, 1, 5, 5], 'three' : [4,4,2,2]}) 

df[['two', 'three']].apply(lambda x: (x - x.min())/(x.max() - x.min())) 

df 

Jetzt möchte ich alle Werte gebunden zwischen 0,01 und 0,99

Dies ist, was ich versucht habe:

def bound_x(x): 
    if x == 1: 
     return x - 0.01 
    elif x < 0.99: 
     return x + 0.01 

df[['two', 'three']].apply(bound_x) 

df

Aber ich die folgende Fehlermeldung:

ValueError: ('The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().', u'occurred at index two') 

Antwort

10

eine App Es gibt, irren clip method, denn das:

import pandas as pd 
df = pd.DataFrame({'one' : ['AAL', 'AAL', 'AAPL', 'AAPL'], 'two' : [1, 1, 5, 5], 'three' : [4,4,2,2]})  
df = df[['two', 'three']].apply(lambda x: (x - x.min())/(x.max() - x.min())) 
df = df.clip(lower=0.01, upper=0.99) 

Ausbeuten

two three 
0 0.01 0.99 
1 0.01 0.99 
2 0.99 0.01 
3 0.99 0.01 

Das Problem mit

df[['two', 'three']].apply(bound_x) 

ist, dass bound_x eine Serie wie df['two'] geben wird und dann if x == 1 erfordert x == 1in einem Booleschen Kontext ausgewertet werden. x == 1 ist eine boolean Serie wie

In [44]: df['two'] == 1 
Out[44]: 
0 False 
1 False 
2  True 
3  True 
Name: two, dtype: bool 

Python versucht, diese Serie zu einem einzigen Booleschen Wert zu reduzieren, True oder False. Pandas folgt der NumPy-Konvention von raising an error when you try to convert a Series (or array) to a bool.

1

So hatte ich ein ähnliches Problem, wo ich benutzerdefinierte Normalisierung wollte, in der ich regelmäßige Perzentil von Datum oder Z-Score war nicht ausreichend. Manchmal wusste ich, was das zulässige Maximum und Minimum der Population war, und wollte es daher anders definieren als meine Probe oder einen anderen Mittelpunkt oder was auch immer! Also baute ich eine benutzerdefinierte Funktion (zusätzliche Schritte in dem Code hier verwendet, um sie so lesbar wie möglich):

def NormData(s,low='min',center='mid',hi='max',insideout=False,shrinkfactor=0.):  
    if low=='min': 
     low=min(s) 
    elif low=='abs': 
     low=max(abs(min(s)),abs(max(s)))*-1.#sign(min(s)) 
    if hi=='max': 
     hi=max(s) 
    elif hi=='abs': 
     hi=max(abs(min(s)),abs(max(s)))*1.#sign(max(s)) 

    if center=='mid': 
     center=(max(s)+min(s))/2 
    elif center=='avg': 
     center=mean(s) 
    elif center=='median': 
     center=median(s) 

    s2=[x-center for x in s] 
    hi=hi-center 
    low=low-center 
    center=0. 

    r=[] 

    for x in s2: 
     if x<low: 
      r.append(0.) 
     elif x>hi: 
      r.append(1.) 
     else: 
      if x>=center: 
       r.append((x-center)/(hi-center)*0.5+0.5) 
      else: 
       r.append((x-low)/(center-low)*0.5+0.) 

    if insideout==True: 
     ir=[(1.-abs(z-0.5)*2.) for z in r] 
     r=ir 

    rr =[x-(x-0.5)*shrinkfactor for x in r]  
    return rr 

Dies dauert in einer Pandas Serie, oder auch nur eine Liste und eine Normalisierung auf Ihren angegebenen niedrig , Mittelpunkt und Höhepunkte. auch da ist ein Schrumpfungsfaktor! Damit können Sie die Daten von 0 und 1 herunterskalieren (das musste ich tun, wenn ich Colormaps in Matplotlib kombiniere: Single pcolormesh with more than one colormap using Matplotlib). So können Sie wahrscheinlich sehen, wie der Code funktioniert, aber im Grunde sagen Sie, dass Sie Werte haben [-5,1,10 ] in einem Beispiel, aber möchten auf einem Bereich von -7 bis 7 normalisieren (also alles über 7, unsere "10" wird effektiv wie eine 7 behandelt) mit einem Mittelpunkt von 2, aber verkleinern Sie es, um eine 256 RGB-Farbtabelle zu passen :

#In[1] 
NormData([-5,2,10],low=-7,center=1,hi=7,shrinkfactor=2./256) 
#Out[1] 
[0.1279296875, 0.5826822916666667, 0.99609375] 

es Ihre Daten auch von innen nach außen drehen kann ... das mag seltsam erscheinen, aber ich fand es für heatmapping nützlich. Angenommen, Sie möchten eine dunklere Farbe für Werte, die näher bei 0 als bei hi/low liegen.Sie könnten Heatmap auf normalisierten Daten basieren, wo insideout = True:

#In[2] 
NormData([-5,2,10],low=-7,center=1,hi=7,insideout=True,shrinkfactor=2./256) 
#Out[2] 
[0.251953125, 0.8307291666666666, 0.00390625] 

So, jetzt „2“, die am nächsten zum Zentrum ist, definiert als „1“ ist der höchste Wert.

Wie auch immer, ich dachte mein Problem war sehr ähnlich zu deiner und diese Funktion könnte dir nützlich sein.

Verwandte Themen