2017-11-17 2 views
0

Ich habe ein kleines eigenartiges Problem. Ich habe einen sehr großen Datenrahmen, den ich zu probieren versuche.Pandas, die jeden n-ten Wert oder den nächsten passenden Wert zum n-ten Wert abtastend

Meine Daten sieht wie folgt aus etwas (zwei Spalten x und y):

x,y 
1,'a' 
1,'b' 
1,'c' 
3,'a' 
3,'b' 
3,'c' 
6,'a' 
6,'b' 
6,'c' 

I auf den Wert von 'x' basiert probieren möchten. Ich möchte eine Probe von allen 32 x Werten (basierend auf der Änderung in x, also möchte ich einmal zwischen 1 und 32 Probe, auch wenn es nur einen Wert von x zwischen 1 und 32 gibt).

Ich wollte etwas tun wie: df[df['x'] % 32 == 0]. Das Problem ist, dass die Werte von x nicht notwendigerweise gleichmäßig beabstandet sind (sie sind zwar "ungefähr", aber nicht immer - wie im Beispiel angegeben). Wenn beispielsweise alle Werte von x in einem bestimmten Teilproblem ungerade sind, wird die obige Abtastung einen leeren Datenrahmen zurückgeben. Effektiv möchte ich einmal alle 32 'xs abtasten, oder nehme den nächstliegenden Wert zum 32. Wert (es ist akzeptabel, am nächsten zu kommen - zum Beispiel, wenn der nächste verfügbare Wert in Ordnung ist), wenn kein solcher Wert existiert.

Also, wenn ich eine Reihe von X [0, 10, 32, 39, 64, 70, 73, 74, 97, 100, 110, 129] hätte, würde ich gerne die Zeilen mit x-Werten entsprechen [0, 32, 64, 97, 129].

Idealerweise könnte ich diese Operation auch vektorisieren, da die Datenrahmen oft ziemlich groß sind.

Antwort

1
df = pd.DataFrame({'x': [1, 1, 1, 3, 3, 3, 6, 6, 6], 
        'y': ['a', 'b', 'c'] * 3}) 

x = [0, 10, 32, 39, 64, 70, 73, 74, 97, 100, 110, 129] 
spacer = 32 

X = pd.Series(x) 
# For each value `n` in the range 0, 32, 64, ..., 129, find the index location of the 
# nearest value in X via `X.sub(n).abs().idxmin()`. Then use these index locations 
# to find the actual target values in X via `loc`. 
target_vals = X.loc[[X.sub(n).abs().idxmin() 
        for n in xrange(0, x[-1], spacer)]].tolist() # `range` in Python 3. 
>>> target_vals 
[0, 32, 64, 97, 129] 

# Sample the target values, taking a sample size of 1. 
df[df['x'].isin(target_vals)].groupby('x').apply(lambda group: group.sample(1)) 
1

Sie können dynamisch Ihre Bins mit Listenkomprehensionen erstellen dann pd.cut Gruppen zu erstellen verwenden und groupby mit sample(1) eine Aufzeichnung für jeweils 32 Werte von ‚X‘ zu bekommen.

df = pd.DataFrame({'X':np.random.randint(0, 100, 5000),'Y':np.random.choice(list('ABCDEF'),5000)}) 

bins = [i for i in np.arange(df.X.min(), df.X.max(), 32)] + [np.inf] 

df.groupby(pd.cut(df.X,bins=bins), as_index=False).apply(lambda x: x.sample(1).values) 

Ausgang:

[[15 'F'] 
[51 'A'] 
[90 'C'] 
[98 'A']] 
Verwandte Themen