2015-09-26 24 views
7

Mam ramkę danych dla transakcji. Każdy wiersz reprezentuje transakcję dwóch pozycji (pomyśl o tym, jak o transakcji z 2 biletami na wydarzenia lub czymś podobnym). Chcę skopiować każdy wiersz na podstawie sprzedanej ilości.Powielony wiersz na podstawie wartości w innej kolumnie

Oto przykładowy kod:

# 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 

To daje dataframe który wygląda tak

Price City Quantity 

20  NYC   2 

30  NYC   2 

5  NYC   2 

300  LA   2 

30  LA   2 

100  LA   2 

Tak więc w powyższym przypadku, każdy wiersz będzie przekształcić dwóch zduplikowanych wierszy. Jeśli kolumna "ilość" wynosiła 3, wiersz ten przekształciłby się w trzy zduplikowane wiersze.

+0

http://stackoverflow.com/help/mcve - gdzie jest kod, który do tego napisałeś i jaki wynik otrzymałeś *? Dobrze opisałeś pożądany wynik, ale nie wydaje się, żeby w tym przypadku było pytanie StackOverflow. Pamiętaj, że SO jest dla * ustalania * kodu, a nie projektowania i pisania kodu. – Prune

+0

@Prune Nie zgadzam się, wydaje się to pasować do opisu konkretnego problemu programistycznego. OP mógłby wykorzystać pewne wskazówki w określeniu skutecznego sposobu rozwiązania tego problemu. Czasami dana osoba nie wie nawet, od czego zacząć, a brzydka próba rozwiązania po prostu zaśmieca pytanie i marnuje czas wszystkich. –

+0

Doceniam rady @ Prune i ogólnie się z tym zgadzam. Myślę, że to dobry sposób na odfiltrowanie leniwych pytań. Ten problem wprawia mnie jednak w zakłopotanie i nie udało mi się zapewnić sensownego miejsca wyjścia dla rozwiązania. – MRA

Odpowiedz

6

Najpierw odtworzyłem twoje dane, używając liczb całkowitych zamiast tekstu. Zmieniłem także ilość, aby łatwiej było zrozumieć problem.

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 

Utworzono nową ramkę DataFrame za pomocą struktury zagnieżdżonej struktury list.

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

Dzięki. Kiedy próbuję tego na moich faktycznych danych, otrzymuję "TypeError: nie mogę przekonwertować serii na " związaną z drugą pętlą for "dla _ w zakresie (df.ix [idx] ['Quantity']))". – MRA

+0

Spróbuj tego: 'dla _ w zakresie (int (df.ix [idx] ['Quantity']))' Możesz także jawnie przekonwertować kolumnę na liczby całkowite: 'df ['Quantity'] = dfQuantity.astype (int) ' – Alexander

+0

Otrzymuję ten sam błąd. – MRA

2

Co z tym podejściem. Zmieniłem trochę dane, aby wywołać sprzedaż 4 biletów.

Używamy np.ones pomocnika() tablicę, odpowiedniej wielkości, a następnie klawisz wiersz kodu: a[np.arange(a.shape[1])[:] > a[:,0,np.newaxis]] = 0

pokazano mi tę technikę tutaj: numpy - update values using slicing given an array value

Potem jej po prostu wezwanie do .stack() i niektóre podstawowe filtry do ukończenia.

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) 

który wygląda następująco:

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 

teraz dostać kolumnę ilość i te w numpy tablicy

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

to mądry nieco

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

i ponownie przypisz z powrotem do df.

df.iloc[:,2:] = a 

a teraz wygląda po df, zauważyć, jak mamy ustawiony na zero w przeszłości liczby Ilość:

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 

która produkuje:

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

Bardzo kreatywne rozwiązanie! Będę musiał zbadać to bardziej uważnie. Sprawdź inną odpowiedź poniżej dla innego podejścia również. bardzo za waszą pomoc, jest to bardzo cenne. – MRA

Powiązane problemy