vlookup используя pandas датафрейм - PullRequest
0 голосов
/ 28 февраля 2020

У меня есть фрейм данных:

df1.tail()
Out[13]: 
               Date  Ticker     P1      P2     cpn  Source      Time
3290644  2020-02-27   COLOM -0.159   0.068     100      G1  21:43:32
3290645  2020-02-27     MEX -0.136  0.0907     100      G1  21:43:32
3290646  2020-02-27  PANAMA -2.071  -1.791     100      G1  21:43:32
3290647  2020-02-27    PERU -1.977  -1.698     100      G1  21:43:32
3290652  2020-02-27  ARGENT   62.1    62.9     500      B1  21:45:55

, который может иметь несколько строк, соответствующих одной дате и тикеру.

У меня есть другой фрейм данных, в котором есть только одна запись для каждой комбинации даты и тикера .

df2.tail()
Out[12]: 
              Date  p-cpn  Ticker
354072  2020-02-27    500  UKRAIN
354073  2020-02-27    100    UKIN
354074  2020-02-27    100  URUGAY
354075  2020-02-27    500    VENZ
354076  2020-02-27    100  VIETNM

df2[df2.Ticker.isin(df1.tail().Ticker)].tail()
Out[38]: 
              Date  p-cpn  Ticker
354002  2020-02-27    100   COLOM
354004  2020-02-27    100   CHILE
354045  2020-02-27    100     MEX
354053  2020-02-27    100    PERU
354056  2020-02-27    100  PANAMA

Для каждого ключа Date + Ticker в df1 я хочу сделать vlookup для столбца 'p-cpn' из df2.

Я пробовал это, но не получилось (в результате NaNs )

df1.merge(df2, on = ['Ticker', 'Date'], how='left').tail()
Out[14]: 
               Date  Ticker     P1      P2     cpn  Source      Time  p-cpn
2333154  2020-02-27   COLOM -0.159   0.068     100      G1  21:43:32    NaN
2333155  2020-02-27     MEX -0.136  0.0907     100      G1  21:43:32    NaN
2333156  2020-02-27  PANAMA -2.071  -1.791     100      G1  21:43:32    NaN
2333157  2020-02-27    PERU -1.977  -1.698     100      G1  21:43:32    NaN
2333158  2020-02-27  ARGENT   62.1    62.9     500      B1  21:45:55    NaN

Тогда я попробовал это, но это займет вечность

def get_p_cpn(data):
    cpn =  df2[(df2.Ticker == data.Ticker.iloc[0]) & (df2.Date == data.Date.iloc[0])]['p-cpn']
    if len(cpn) == 0:
        return np.nan
    else:
        return cpn.iloc[0]
df1['p-cpn'] = df1.groupby(['Date', 'Ticker']).apply(lambda x: get_p_cpn(x))

, поскольку кадры данных большие

df1.shape
Out[15]: (2333159, 7)

df2.shape
Out[16]: (354077, 3)

Есть ли более быстрый способ сделать это?

1 Ответ

0 голосов
/ 28 февраля 2020

Протестировано и получено одинаковое значение для вашей функции и merge:

def get_p_cpn(data):
    cpn =  df2[(df2.Ticker == data.Ticker.iloc[0]) & (df2.Date == data.Date.iloc[0])]['p-cpn']
    if len(cpn) == 0:
        return np.nan
    else:
        return cpn.iloc[0]
df1 = df1.join(df1.groupby(['Date', 'Ticker']).apply(lambda x: get_p_cpn(x)).rename('p-cpn'), on=['Date','Ticker'])
print (df1)
               Date  Ticker      P1       P2  cpn Source      Time  p-cpn
3290644  2020-02-27   COLOM  -0.159   0.0680  100     G1  21:43:32  100.0
3290645  2020-02-27     MEX  -0.136   0.0907  100     G1  21:43:32  100.0
3290646  2020-02-27  PANAMA  -2.071  -1.7910  100     G1  21:43:32  100.0
3290647  2020-02-27    PERU  -1.977  -1.6980  100     G1  21:43:32  100.0
3290652  2020-02-27  ARGENT  62.100  62.9000  500     B1  21:45:55    NaN

df1 = df1.merge(df2, on = ['Ticker', 'Date'], how='left')
print (df1)
         Date  Ticker      P1       P2  cpn Source      Time  p-cpn_x  p-cpn_y
0  2020-02-27   COLOM  -0.159   0.0680  100     G1  21:43:32    100.0    100.0
1  2020-02-27     MEX  -0.136   0.0907  100     G1  21:43:32    100.0    100.0
2  2020-02-27  PANAMA  -2.071  -1.7910  100     G1  21:43:32    100.0    100.0
3  2020-02-27    PERU  -1.977  -1.6980  100     G1  21:43:32    100.0    100.0
4  2020-02-27  ARGENT  62.100  62.9000  500     B1  21:45:55      NaN      NaN
...