2015-09-26 12 views
7

Ich habe einen Datenrahmen von Transaktionen. Jede Zeile repräsentiert eine Transaktion von zwei Elementen (denken Sie daran wie eine Transaktion von 2 Ereignistickets oder etwas). Ich möchte jede Zeile basierend auf der verkauften Menge duplizieren.Doppelte Zeile basierend auf Wert in verschiedenen Spalte

Hier ist Beispielcode:

# dictionary of transactions 

d = {'1': ['20', 'NYC', '2'], '2': ['30', 'NYC', '2'], '3': ['5', 'NYC', '2'], \ 
    '4': ['300', 'LA', '2'], '5': ['30', 'LA', '2'], '6': ['100', 'LA', '2']} 

columns=['Price', 'City', 'Quantity'] 

# create dataframe and rename columns 

df = pd.DataFrame.from_dict(data=d, orient='index') 
df.columns = columns 

Dieses eine Datenrahmen erzeugt, wie diese oben

Price City Quantity 

20  NYC   2 

30  NYC   2 

5  NYC   2 

300  LA   2 

30  LA   2 

100  LA   2 

So im Fall sieht, wird jede Zeile in zwei doppelte Zeilen verwandeln. Wenn die Spalte "Menge" 3 ist, wird diese Zeile in drei doppelte Zeilen umgewandelt.

+0

http://stackoverflow.com/help/mcve - wo ist der Code, den du dafür geschrieben hast, und welche Ausgabe * hast du bekommen? Sie haben die gewünschte Ausgabe gut genug beschrieben, aber es scheint keine StackOverflow-Frage zu geben. Denken Sie daran, dass SO für Code * Fixing * nicht Code Design und Schreiben ist. – Prune

+0

@Prune Ich stimme nicht zu, das scheint die Beschreibung eines bestimmten Programmierproblems zu passen. Das OP könnte einige Hinweise dazu verwenden, einen effizienten Weg zur Lösung dieses Problems zu finden. Manchmal weiß eine Person nicht einmal, wo sie anfangen soll, und ein hässlicher Lösungsversuch wirft nur die Frage auf und verschwendet die Zeit aller Menschen. –

+0

Ich weiß den Ratschlag von @ Prune zu schätzen und stimme ihm im Allgemeinen zu. Ich denke, das ist ein guter Weg, um rein faule Fragen herauszufiltern. Dieses Problem hat mich jedoch überrascht und ich war nicht in der Lage, einen sinnvollen Startplatz für eine Lösung zu bieten. – MRA

Antwort

6

Zuerst habe ich Ihre Daten mit Ganzzahlen anstelle von Text neu erstellt. Ich habe auch die Menge variiert, damit man das Problem leichter verstehen kann.

d = {1: [20, 'NYC', 1], 2: [30, 'NYC', 2], 3: [5, 'SF', 3],  
    4: [300, 'LA', 1], 5: [30, 'LA', 2], 6: [100, 'SF', 3]} 

columns=['Price', 'City', 'Quantity'] 
# create dataframe and rename columns 

df = pd.DataFrame.from_dict(data=d, orient='index').sort_index() 
df.columns = columns 

>>> df 
    Price City Quantity 
1  20 NYC   1 
2  30 NYC   2 
3  5 SF   3 
4 300 LA   1 
5  30 LA   2 
6 100 SF   3 

Ich habe einen neuen DataFrame erstellt, indem ich eine Verständnisstruktur für verschachtelte Listen verwendet habe.

df_new = pd.DataFrame([df.ix[idx] 
         for idx in df.index 
         for _ in range(df.ix[idx]['Quantity'])]).reset_index(drop=True) 
>>> df_new 
    Price City Quantity 
0  20 NYC   1 
1  30 NYC   2 
2  30 NYC   2 
3  5 SF   3 
4  5 SF   3 
5  5 SF   3 
6  300 LA   1 
7  30 LA   2 
8  30 LA   2 
9  100 SF   3 
10 100 SF   3 
11 100 SF   3 
+0

Danke. Wenn ich es auf meinen tatsächlichen Daten versuche, erhalte ich einen "TypeError: kann die Reihe zu " nicht umwandeln, die auf die zweite for-Schleife "für _ in Bereich (df.ix [idx] ['Quantity'])" bezogen wird. – MRA

+0

Probieren Sie dies aus: 'für _ im Bereich (int (df.ix [idx] ['Menge']))' Sie können die Spalte auch explizit in ganze Zahlen umwandeln: 'df ['Menge'] = dfQuantity.astype (int) ' – Alexander

+0

Ich bekomme den gleichen Fehler. – MRA

2

Wie wäre es mit diesem Ansatz? Ich habe Ihre Daten leicht geändert, um einen Verkauf von 4 Tickets auszurufen.

Wir verwenden einen Helfer np.ones() Array, von geeigneter Größe, und dann der Schlüsselcodezeile ist: numpy - update values using slicing given an array value

Dann ist es einfach ein Anruf an: a[np.arange(a.shape[1])[:] > a[:,0,np.newaxis]] = 0

ich diese Technik hier gezeigt wurde .stack() und einige grundlegende Filterung zu vervollständigen.

d = {'1': ['20', 'NYC', '2'], '2': ['30', 'NYC', '2'], '3': ['5', 'NYC', '2'], \ 
    '4': ['300', 'LA', '2'], '5': ['30', 'LA', '4'], '6': ['100', 'LA', '2']} 

columns=['Price', 'City', 'Quantity'] 
df = pd.DataFrame.from_dict(data=d, orient='index') 
df.columns = columns 
df['Quantity'] = df['Quantity'].astype(int) 

# make a ones array 
my_ones = np.ones(shape=(len(df),df['Quantity'].max())) 

# turn my_ones into a dataframe same index as df so we can join it to the right hand side. Plenty of other ways to achieve the same outcome. 
df_my_ones = pd.DataFrame(data =my_ones,index = df.index) 

df = df.join(df_my_ones) 

, die wie folgt aussieht:

Price City Quantity 0 1 2 3 
1 20 NYC   2 1 1 1 1 
3  5 NYC   2 1 1 1 1 
2 30 NYC   2 1 1 1 1 
5 30 LA   4 1 1 1 1 
4 300 LA   2 1 1 1 1 

jetzt die Spalte Menge bekommen und die, die in eine numpy Array

a = df.iloc[:,2:].values 

Dies ist die clevere Bit

a[np.arange(a.shape[1])[:] > a[:,0,np.newaxis]] = 0 

und df neu zuweisen.

df.iloc[:,2:] = a 

und jetzt df sieht wie folgt aus, merken, wie wir auf Null über die Anzahl Anzahl festgelegt haben:

Price City Quantity 0 1 2 3 
1 20 NYC   2 1 1 0 0 
3  5 NYC   2 1 1 0 0 
2 30 NYC   2 1 1 0 0 
5 30 LA   4 1 1 1 1 
4 300 LA   2 1 1 0 0 

df.set_index(['Price','City','Quantity'],inplace=True) 
df = df.stack().to_frame() 
df.columns = ['sale_flag'] 
df.reset_index(inplace=True) 
print df[['Price','City', 'Quantity']][df['sale_flag'] !=0] 
print df 

, die produziert:

Price City Quantity 
0  20 NYC   2 
1  20 NYC   2 
4  5 NYC   2 
5  5 NYC   2 
8  30 NYC   2 
9  30 NYC   2 
12 30 LA   4 
13 30 LA   4 
14 30 LA   4 
15 30 LA   4 
16 300 LA   2 
17 300 LA   2 
+0

Sehr kreative Lösung! Ich muss es genauer untersuchen. Überprüfen Sie die andere Antwort unten für einen anderen Ansatz. Danke viel für Ihre Hilfe, es ist sehr geschätzt. – MRA

Verwandte Themen