2015-09-26 5 views
7

У меня есть dataframe транзакций. Каждая строка представляет собой транзакцию из двух элементов (считайте ее транзакцией из двух билетов на события или что-то еще). Я хочу дублировать каждую строку на основе проданного количества.Повторяющаяся строка на основе значения в разных столбцах

Вот пример кода:

# 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 

Это производит dataframe, который выглядит, как этот

Price City Quantity 

20  NYC   2 

30  NYC   2 

5  NYC   2 

300  LA   2 

30  LA   2 

100  LA   2 

Таким образом, в приведенном выше случае, каждая строка будет трансформироваться в две повторяющиеся строки. Если столбец «количество» равен 3, то эта строка преобразуется в три повторяющиеся строки.

+0

http://stackoverflow.com/help/mcve - где код, который вы написали для этого, и какой вывод * * вы получили? Вы достаточно хорошо описали желаемый результат, но в этом вопросе не возникает вопрос StackOverflow. Помните, что SO предназначен для исправления кода *, а не для проектирования и записи кода. – Prune

+0

@Prune Я не согласен, это похоже на описание конкретной проблемы программирования. ОП может использовать некоторые рекомендации с определением эффективного способа решения этой проблемы. Иногда человек даже не знает, с чего начать, и уродливая попытка решения просто загромождает вопрос и отнимает у всех время. –

+0

Я ценю совет @ Prune, и я согласен с ним. Я думаю, что это хороший способ отфильтровать чисто ленивые вопросы. Эта проблема, хотя и имеет тупик, и я не смог дать значимого стартового места для решения. – MRA

ответ

6

Во-первых, я воссоздал ваши данные, используя целые числа вместо текста. Я также менял количество, чтобы легче понять проблему.

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 

Я создал новый DataFrame, используя структуру вложенного списка.

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

Спасибо. Когда я пытаюсь использовать мои фактические данные, я получаю «TypeError: не могу преобразовать серию в », связанную со вторым циклом «for» в диапазоне (df.ix [idx] ['Quantity']) ». – MRA

+0

Попробуйте следующее: 'for _ in range (int (df.ix [idx] ['Quantity']))' Вы также можете явно преобразовать столбец в целые числа: 'df ['Quantity'] = dfQuantity.astype (int) ' – Alexander

+0

Я получаю ту же ошибку. – MRA

2

Как насчет этого подхода. Я немного изменил ваши данные, чтобы вызвать продажу 4 билетов.

Мы используем вспомогательные np.ones() массив, подходящего размера, а затем ключ строка кода: a[np.arange(a.shape[1])[:] > a[:,0,np.newaxis]] = 0

мне показали эту технику здесь: numpy - update values using slicing given an array value

Тогда его просто вызов .stack() и некоторую базовую фильтрацию для завершения.

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) 

, который выглядит следующим образом:

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 

теперь получить столбец Количество и те, в Numpy массив

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

Это умный кусочек

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

и повторно назначить обратно в df.

df.iloc[:,2:] = a 

и теперь ДФ выглядит следующим образом, обратите внимание, как мы установили к нулю мимо числа в Количество:

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 

, который производит:

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

Очень творческое решение! Мне нужно будет изучить его более тщательно. Проверьте другой ответ ниже для другого подхода. много для вашей помощи. Это очень ценно. – MRA

Смежные вопросы