#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:
Вот мой ответ, надеюсь, это поможет:
- преобразовать столбец ‘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)
- Создайте все возможные комбинации и сохраните их в другом фрейме данных:
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')]