2016-06-01 1 views
0

У меня есть дата-карта, имеющая все данные транзакций клиентов. столбцы - mailid, txn_date, city. Теперь у меня есть ситуация, когда мне приходится рассматривать клиент от 01jan2016 и для каждого из mailid в том, что я должен извлекать их данные txn из базового файла и учитывая их последние данные за 12 месяцев (txn date между последней датой Txn и -365days timedelta) затем выяснив их максимальное имя города.Зацикливание над фреймворком данных и получение связанных данных из другого фрейма данных: PANDAS

образца база dataframe

#df 
maild txn_date city 
satya 2015-07-21 a 
satya 2015-08-11 b 
satya 2016-05-11 c 
xyz  2016-06-01 f 
satya 2016-06-01 a 
satya 2016-06-01 b 

Как мне нужно Касты от 2016-01-01, так что я сделал

d = df[['mailid', 'txn-date']][df['txn_date'] >= '2016-01-01'] 

теперь для каждого mailid в д я должен принести каждый из их последней сделки 12month данные из базы Dataframe df и рассчитывают их максимальный город. Для этого я использую для цикла как

x = d.groupby(['mailid'])['txn-date'].max().reset_index() #### finding their last transacted date to find out a 12 Month back date 
x['max_city'] = 'N' ## giving default value as 'N' 
for idx,row in x.iterrows(): 
g = row[1].date() 
h = g-timedelta(days=365) ###getting the last 12 Month date 
y = df[(df['mailid']==row[0]) & (df['txn_date'] >= str(h))] 
y.sort(['txn_date'],ascending=True,inplace=True) ### sorting it bcoz i want to consider the last txn when count for one or more cities become same 
c = y.groupby(['mailid','city']).size().reset_index() 
v = c.groupby(['mailid'])[0].max().reset_index() 
dca = pd.merge(y,c,on=['mailid','city'],how='left') 
dcb = pd.merge(dca,v,on=['mailid',0]) 
m = dcb.drop_duplicates(['mailid'],take_last=True) 
row[2] = m['city'].unique()[0] 

о/р:

maild max_city 
satya b ### as in last 12 month 2016-06-01 2015-06-01 txn in a=2 b= 2 so last is b so will consider b as max city 
xyz  f 

Хотя мой код работает (я уверен, что это не-организованной и не собственно именования не используется, как я практиковал) для небольшого фрагмента данных, и цикл попадет в основную базовую базу данных df для каждого клиента, присутствующего в кадре данных x.

Так что моя главная проблема заключается в том, что мой df будет состоять из 100Mln строк и x будет из 6 миллионов строк. то цикл for выполнит 6Mln раз и ударит df для извлечения согласованных данных mailid и выполнит операцию по поиску максимального транзакционного города.

, если в течение 1 минут он рассчитает 3 максимум города mailid. то за 6 млн. потребуется 2 млн. минут ... что будет серьезной проблемой ...

Так что вам нужно знать, как оптимизировать сценарий. Потребительская атака на базовую базу меньше времени и применение более удобных PANDAS путь к тому, что (чего я еще не могу сделать) ...

Пожалуйста, предложите !!!! Спасибо в Adv.

+0

Город - это текстовая колонка, и вы хотите объединить * максимальное название города с транзакцией *? Вы имеете в виду макс. Города? Или в алфавитном наивысшем городе? – Parfait

+0

@ Parfait-Ровно !!! Я хочу макс. подсчета городов, или вы можете сказать, что любимый город ... – Satya

ответ

1

Вы можете использовать groupby и применять функциональность более эффективно.

Группа по городу и maild и получите максимальную дату и общее количество транзакций. Сортировка по максимальной дате.

g=d.groupby(['maild','city'])['txn_date'].agg(['count','max']).sort_values('max',ascending=False) 

Тогда группа что только MAILD и получить индекс самого высокого графа

g.groupby(level='maild')['count'].agg(lambda x:pd.Series.argmax(x)[1]) 

-

maild 
satya a 
xyz  f 

Btw, в вашем примере вы имеете транзакции для сатья как для а и b на 2016-01-01. Как вы решили, что b - правильный ответ?

1

Вот альтернатива, которая может быть немного легче читать:

def f(g): 
    dc=g.groupby('city')['txn_date'] 
    dc_sorted=dc.agg(['count','max']).sort_values('max',ascending=False) 
    return dc_sorted['count'].argmax() 

d.groupby(['maild']).apply(f) 

Однако, я подозреваю, что apply будет иметь некоторые проблемы с производительностью на очень больших таблиц.

+0

@ Victor-Ваше предложение отлично работает на весь фрейм данных, но у меня есть другое условие, например --- для каждого почтового идентификатора я должен рассмотреть их LAST 12Months Transactions .. .so как подобрать это условие в вашем коде? ех. если fo r 'satya' сказать, что есть еще одна дата txn '2014-02-01', то это не следует рассматривать как его последняя дата txn - '2016-06-01', а дельта 365 дней - '2015-06-01 «... так и нужно добиться этой ситуации. вы можете помочь !!! – Satya

+0

кажется, что вы можете просто полностью отфильтровать весь набор данных, чтобы исключить все меньше, чем 12 месяцев назад? –

0

Рассмотрите функцию apply и transform. Первая группа запусков рассчитывается на maild и city в соответствии с временным интервалом, а вторая максимизирует счет на maild. Наконец, фильтрациядержит пар, чей счет равен максимальному счету.

def last12mos(row): 
    row['count'] = 0 
    row.loc[row['txn_date'] >= row['txn_date'].max() - timedelta(days=365), 'count'] = 1 
    row['count'] = row['count'].sum() 
    return(row) 

basedf = basedf.groupby(['maild', 'city']).apply(last12mos)  
basedf['maxcount'] = basedf.groupby(['maild'])['count'].transform(max) 

finaldf = basedf[basedf['count'] == basedf['maxcount']].\ 
              groupby(['maild', 'city']).aggregate(max) 

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

  • Нет связанных вопросов^_^