2016-02-11 3 views
0

У меня есть два кадра данных: A (users_df) и B (coffeeA_df), содержащие временные метки в формате epoch. Для каждой отметки времени в A мне нужно найти, находится ли какая-то временная метка (на самом деле, временное окно минус/плюс несколько секунд с отметки времени) где-то в B.
Если это так, мне нужно извлечь некоторые значения из строка в B и создать новый фрейм данных. Я сделал это, и он работает, но я использовал .iterrows() во вложенном цикле, но, как вы можете себе представить, он очень медленный и неэффективный (учитывая размер моего текущего набора данных, он занимает около 2 часов на файл, и мне нужно обработать около 100 файлов).В Pandas, как найти появление одного значения из одного фрейма данных в другом фрейме?

Есть ли более быстрый способ решения этой проблемы с использованием функций/методов Pandas? Любые советы будут высоко оценены.

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

users_df:

Unnamed: 0 Name  Date  Time    Drink 
0   0 User1 14/09/2015 13:15:00 water (hot + cold) 
1   1 User2 14/09/2015 13:16:00  Instant coffee 
2   2 User3 14/09/2015 16:54:00     tea 
3   3 User2 15/09/2015 9:26:00 coffee + hot water 
4   4 User4 15/09/2015 9:43:00   cold water 
5   5 User1 15/09/2015 10:11:00   tea + milk 
6   6 User5 15/09/2015 10:15:00   cold water 
7   7 User4 15/09/2015 11:03:00   cold water 
8   8 User1 15/09/2015 11:10:00   cold water 
9   9 User4 15/09/2015 11:49:00   cold water 

coffeeA_df:

Unnamed: 0 NodeID Coffee   Epoch 
0  13334 M002  1 1442241969146 
1  13335 M002  1 1442241969648 
2  13336 M002  1 1442241970150 
3  13337 M002  1 1442241970655 
4  13338 M002  1 1442241971156 
5  13339 M002  1 1442241971657 
6  13340 M002  1 1442241972159 
7  13341 M002  1 1442241972663 
8  13342 M002  1 1442241973164 
9  13343 M002  1 1442241973666 

Вот моя неэффективная часть кода:

for indexUsers, row in users_df.iterrows(): 

    #need to convert from String Date/Time into epoch, as coffeeA_df is in epoch 
    time_ofAction=users_df.get_value(indexUsers, 'Time') 
    day_ofAction=users_df.get_value(indexUsers, 'Date ') 
    tStamp=day_ofAction+' ' +time_ofAction 

    action_epoch = int(time.mktime(time.strptime(tStamp, pattern)))+DST 


    #check for time window in coffee data 
    for index, row in coffeeA_df.iterrows(): 
     time_coffeeA=((coffeeA_df.get_value(index, ' Epoch'))/1000) #normalise epochs to seconds, was in milliseconds 

     #check for +- 5 min time window=300 seconds 

     if ((time_coffeeA+timeWindow)>=action_epoch) and ((time_coffeeA-timeWindow)<=action_epoch): 
      sensorData = row.copy() 

      #obtain desired values from this DF 
      sensorData['Activity']=users_df.get_value(indexUsers,'Drink') 
      sensorData['User']=users_df.get_value(indexUsers,'Name') 
      sensorData['RegisteredActivityTime']=action_epoch 

      #append into final DataFrame 
      coffeeClean = coffeeClean.append(sensorData, ignore_index=True) 
+0

Можете ли вы предоставить несколько строк из обоих фреймов данных, по крайней мере, с одной совпадающей строкой? – IanS

+0

Спасибо. Я редактировал вопрос, чтобы включить их. – Waldo

+0

Кроме того, это не совсем подходящая строка. Учитывая характер сбора данных, эпохи из источника (coffeeA_df) собираются в миллисекундах, тогда как эпохи user_df преобразуются из строки, которая находится в секундах, следовательно, мне нужно искать из окна времени, а не точное совпадение. – Waldo

ответ

0

Первым шагом было бы преобразовать в эпоху внутри dataframe пользователей :

users_df['Epoch'] = users_df['Date'] + ' ' + users_df['Time'] 
users_df['Epoch'] = users_df['Epoch'].apply(lambda tStamp: int(time.mktime(time.strptime(tStamp, pattern)))) 

Теперь для данной эпохи, вы можете выбрать соответствующую строку с этим:

time_coffeeA = coffeeA_df['Epoch'].iloc[0]/1000 
users_df[(users_df['Epoch'] - time_coffeeA).abs() < timeWindow] 

С вашим примером, выход:

Name  Date  Time Drink  Epoch 
2 User3 14/09/2015 16:54:00 tea 1442242440 

Теперь вы можете применить эту функцию к весь кофейный чемодан:

coffeeA_df.apply(lambda row: users_df[(users_df['Epoch'] - row['Epoch']/1000).abs() < timeWindow].iloc[0], axis=1) 

В случае, если временное окно возвращает несколько строк, я произвольно выбираю первый, следовательно, .iloc[0] в конце.

Примечание: Мне нужно было использовать timeWindow = 500 # not 300, чтобы найти матч.

+0

Большое спасибо! Я попробую и отчитаю. ура! – Waldo

+0

Если вы указываете, есть несколько строк, есть ли способ получить их все, а не только первый, как в вашем решении? благодаря! – Waldo

+0

Мне нужно подумать об этом. Я думаю, у вас также есть случаи, когда нет подходящей строки, не так ли? – IanS

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