найти все пары строк в фрейме данных pandas с интервалом в 60 секунд

#python #pandas #dataframe

#python #pandas #фрейм данных

Вопрос:

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

 >>> df
   X         Y
0  a  2021-02-26 06:30:00
1  b  2021-02-26 06:30:30
2  c  2021-02-26 06:30:45
3  d  2021-02-26 06:31:30
4  e  2021-02-26 06:31:50
 

Я хочу найти все пары X, где Y находится в пределах 60 секунд.

Поэтому я хочу:

a, b

a, c

b, c

b, d

c, d

d, e

Я знаю, что могу использовать цикл по данным и сравнивать, но я надеюсь, что есть более элегантный способ сделать это, например, с помощью filter и grouper

Комментарии:

1. Если вы беспокоитесь о времени, python не такой быстрый язык для начала.

Ответ №1:

Попробуйте это:

 import pandas as pd
from io import StringIO
from datetime import timedelta

data = StringIO(
"""
X  Y
0  a  2021-02-26 06:30:00
1  b  2021-02-26 06:30:30
2  c  2021-02-26 06:30:45
3  d  2021-02-26 06:31:30
4  e  2021-02-26 06:31:50
""")

df = pd.read_csv(data, sep='  ')

df['Y'] = pd.to_datetime(df['Y'])

# add key for cross join
df['key'] = 0

# cross join
df = df.merge(df, on='key', suffixes = ('', '_intermediate'))

df[(df['Y_intermediate'] > df['Y'])
   amp; (df['Y_intermediate'] - df['Y'] <= timedelta(seconds=60))][['X', 'X_intermediate']]

df
 

дает:

выходной результат

Ответ №2:

Здесь заманчиво использовать .merge_asof функцию:

 import pandas as pd
from io import StringIO

data = StringIO(
"""
X  Y
0  a  2021-02-26 06:30:00
1  b  2021-02-26 06:30:30
2  c  2021-02-26 06:30:45
3  d  2021-02-26 06:31:30
4  e  2021-02-26 06:31:50
""".strip())

df = pd.read_csv(data, sep='  ')
df['Y'] = pd.to_datetime(df['Y'])

pd.merge_asof(df, df, on='Y', tolerance=pd.Timedelta('60 s'), allow_exact_matches=False, direction='forward')
 

Однако, как вы можете видеть из выходных данных, он будет соответствовать только одному элементу для каждой левой записи. Поскольку вас интересуют неуникальные совпадения, это более сложная задача, которая потребует формирования всех потенциальных комбинаций значений.

Ответ №3:

Вот мой ответ, надеюсь, это поможет:

  1. преобразовать столбец ‘X’ в индекс:
 df =  pd.DataFrame({
        'X': [ 'a','b','c','d','e'],
        'Y' : [ '2021-02-26 06:30:00','2021-02-26 06:30:30','2021-02-26 06:30:45','2021-02-26 06:31:30', '2021-02-26 06:31:50'],
       })
df["Y"]= pd.to_datetime(df["Y"])
df.index = df['X'] 
df = df.drop('X',axis=1)
 
  1. Создайте все возможные комбинации и сохраните их в другом фрейме данных:
 comb_list = list(combinations(df.index.to_list(),2))
df2 = pd.DataFrame(comb_list)
df2.index = comb_list
df2['Result'] = df2.apply(lambda row : df.loc[row[1]]['Y'] - df.loc[row[0]]['Y'] , axis = 1 )
output = df2[df2['Result'] <= pd.Timedelta(60,'S')].index.to_list()
print(output)
[('a', 'b'), ('a', 'c'), ('b', 'c'), ('b', 'd'), ('c', 'd'), ('d', 'e')]