Légèrement modifié à partir de: Python Pandas Dataframe: Normaliser les données entre 0.01 et 0.99? mais suite à certains commentaires, j'ai pensé que c'était pertinent (désolé si cela est considéré comme un repost cependant...)
Je voulais une normalisation personnalisée car le percentile régulier des données ou le z-score n'était pas adéquat. Parfois je savais quel était le maximum et le minimum possibles de la population, et donc je voulais le définir autrement que mon échantillon, ou un midpoint différent, ou autre chose! Cela peut souvent être utile pour redimensionner et normaliser des données pour les réseaux neuronaux où vous voulez que toutes les entrées soient entre 0 et 1, mais certaines de vos données peuvent nécessiter d'être redimensionnées de manière plus personnalisée... car les percentiles et les écarts-types supposent que votre échantillon couvre la population, mais parfois nous savons que ce n'est pas vrai. C'était également très utile pour moi lorsque je visualisais des données dans des cartes thermiques. J'ai donc créé une fonction personnalisée (j'ai ajouté des étapes supplémentaires dans le code ici pour le rendre aussi lisible que possible) :
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 xhi:
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
Cela prendra une série pandas, ou même juste une liste et la normalisera à vos points bas, centraux et hauts spécifiés. il y a aussi un facteur de rétrécissement ! pour vous permettre de réduire l'échelle des données loin des extrémités 0 et 1 (j'ai dû le faire lorsque je combinai les cartes de couleur dans matplotlib : Tracer une seule pcolormesh avec plus d'une carte de couleur en utilisant Matplotlib) Donc vous pouvez probablement voir comment le code fonctionne, mais en gros, disons que vous avez des valeurs [-5,1,10] dans un échantillon, mais que vous voulez normaliser selon une plage de -7 à 7 (donc tout ce qui dépasse 7, notre "10" est traité comme un 7 efficacement) avec un midpoint de 2, mais le rétrécir pour s'adapter à une colormap RGB de 256 :
#In[1]
NormData([-5,2,10],low=-7,center=1,hi=7,shrinkfactor=2./256)
#Out[1]
[0.1279296875, 0.5826822916666667, 0.99609375]
Il peut également retourner vos données à l'envers... cela peut sembler étrange, mais j'ai trouvé cela utile pour la cartographie thermique. Disons que vous voulez une couleur plus sombre pour les valeurs plus proches de 0 plutôt que hi/low. Vous pouvez cartographier thermiquement sur la base de données normalisées où 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]
Maintenant, "2" qui est plus proche du centre, défini comme "1" est la valeur la plus élevée.
En tout cas, j'ai pensé que mon application était pertinente si vous cherchez à redimensionner les données de manière différente, ce qui pourrait vous être utile.