看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
pandas.merge_asof
函数用于按键值进行近似合并,尤其适用于时间序列数据或其他需要根据最近匹配进行合并的场景。
pandas.merge_asof
主要用于 pandas.DataFrame
类型的数据集。函数会返回一个新的 DataFrame
,其中包含根据近似键值合并后的数据。
按关键帧距离执行合并。这类似于左连接,除了我们在最近键而不是相等键上进行匹配。两个DataFrames都必须按键排序。
pandas.merge_asof(
left,
right,
on=None,
left_on=None,
right_on=None,
left_index=False,
right_index=False,
by=None,
left_by=None,
right_by=None,
suffixes=('_x', '_y'),
tolerance=None,
allow_exact_matches=True,
direction='backward'
)
left:
DataFrame
right:
DataFrame
on:
str
left_on:
str
on
未指定,可以通过此参数指定左侧的合并键。right_on:
str
on
未指定,可以通过此参数指定右侧的合并键。left_index:
bool
right_index:
bool
by:
str
或 list
left_by:
str
或 list
right_by:
str
或 list
suffixes:
tuple
tolerance:
Timedelta
或 int
allow_exact_matches:
bool
False
,则不允许精确匹配,只能选择最近的匹配。direction:
str
('backward'
, 'forward'
, 'nearest'
)'backward'
表示找到小于或等于合并键的值,'forward'
表示找到大于或等于合并键的值,'nearest'
表示找到最接近的值。DataFrame
,包含根据近似键值合并后的数据。merge_asof
可以用于填充数据集中根据时间或顺序缺失的数据。left = pd.DataFrame({"a": [1, 5, 10], "left_val": ["a", "b", "c"]})
left
'''
a left_val
0 1 a
1 5 b
2 10 c
'''
right = pd.DataFrame({"a": [1, 2, 3, 6, 7], "right_val": [1, 2, 3, 6, 7]})
right
'''
a right_val
0 1 1
1 2 2
2 3 3
3 6 6
4 7 7
'''
pd.merge_asof(left, right, on="a")
'''
a left_val right_val
0 1 a 1
1 5 b 3
2 10 c 7
'''
pd.merge_asof(left, right, on="a", allow_exact_matches=False)
'''
a left_val right_val
0 1 a NaN
1 5 b 3.0
2 10 c 7.0
'''
pd.merge_asof(left, right, on="a", direction="forward")
'''
a left_val right_val
0 1 a 1.0
1 5 b 6.0
2 10 c NaN
'''
pd.merge_asof(left, right, on="a", direction="nearest")
'''
a left_val right_val
0 1 a 1
1 5 b 6
2 10 c 7
'''
# 我们也可以使用索引的DataFrames。
left = pd.DataFrame({"left_val": ["a", "b", "c"]}, index=[1, 5, 10])
left
'''
left_val
1 a
5 b
10 c
'''
right = pd.DataFrame({"right_val": [1, 2, 3, 6, 7]}, index=[1, 2, 3, 6, 7])
right
'''
right_val
1 1
2 2
3 3
6 6
7 7
'''
pd.merge_asof(left, right, left_index=True, right_index=True)
'''
left_val right_val
1 a 1
5 b 3
10 c 7
'''
# 这是一个真实世界的时间序列示例
quotes = pd.DataFrame(
{
"time": [
pd.Timestamp("2016-05-25 13:30:00.023"),
pd.Timestamp("2016-05-25 13:30:00.023"),
pd.Timestamp("2016-05-25 13:30:00.030"),
pd.Timestamp("2016-05-25 13:30:00.041"),
pd.Timestamp("2016-05-25 13:30:00.048"),
pd.Timestamp("2016-05-25 13:30:00.049"),
pd.Timestamp("2016-05-25 13:30:00.072"),
pd.Timestamp("2016-05-25 13:30:00.075")
],
"ticker": [
"GOOG",
"MSFT",
"MSFT",
"MSFT",
"GOOG",
"AAPL",
"GOOG",
"MSFT"
],
"bid": [720.50, 51.95, 51.97, 51.99, 720.50, 97.99, 720.50, 52.01],
"ask": [720.93, 51.96, 51.98, 52.00, 720.93, 98.01, 720.88, 52.03]
}
)
quotes
'''
time ticker bid ask
0 2016-05-25 13:30:00.023 GOOG 720.50 720.93
1 2016-05-25 13:30:00.023 MSFT 51.95 51.96
2 2016-05-25 13:30:00.030 MSFT 51.97 51.98
3 2016-05-25 13:30:00.041 MSFT 51.99 52.00
4 2016-05-25 13:30:00.048 GOOG 720.50 720.93
5 2016-05-25 13:30:00.049 AAPL 97.99 98.01
6 2016-05-25 13:30:00.072 GOOG 720.50 720.88
7 2016-05-25 13:30:00.075 MSFT 52.01 52.03
'''
trades = pd.DataFrame(
{
"time": [
pd.Timestamp("2016-05-25 13:30:00.023"),
pd.Timestamp("2016-05-25 13:30:00.038"),
pd.Timestamp("2016-05-25 13:30:00.048"),
pd.Timestamp("2016-05-25 13:30:00.048"),
pd.Timestamp("2016-05-25 13:30:00.048")
],
"ticker": ["MSFT", "MSFT", "GOOG", "GOOG", "AAPL"],
"price": [51.95, 51.95, 720.77, 720.92, 98.0],
"quantity": [75, 155, 100, 100, 100]
}
)
trades
'''
time ticker price quantity
0 2016-05-25 13:30:00.023 MSFT 51.95 75
1 2016-05-25 13:30:00.038 MSFT 51.95 155
2 2016-05-25 13:30:00.048 GOOG 720.77 100
3 2016-05-25 13:30:00.048 GOOG 720.92 100
4 2016-05-25 13:30:00.048 AAPL 98.00 100
'''
# By default we are taking the asof of the quotes
pd.merge_asof(trades, quotes, on="time", by="ticker")
'''
time ticker price quantity bid ask
0 2016-05-25 13:30:00.023 MSFT 51.95 75 51.95 51.96
1 2016-05-25 13:30:00.038 MSFT 51.95 155 51.97 51.98
2 2016-05-25 13:30:00.048 GOOG 720.77 100 720.50 720.93
3 2016-05-25 13:30:00.048 GOOG 720.92 100 720.50 720.93
4 2016-05-25 13:30:00.048 AAPL 98.00 100 NaN NaN
'''
# 我们只在报价时间和交易时间之间的2毫秒内
pd.merge_asof(
trades, quotes, on="time", by="ticker", tolerance=pd.Timedelta("2ms")
)
'''
time ticker price quantity bid ask
0 2016-05-25 13:30:00.023 MSFT 51.95 75 51.95 51.96
1 2016-05-25 13:30:00.038 MSFT 51.95 155 NaN NaN
2 2016-05-25 13:30:00.048 GOOG 720.77 100 720.50 720.93
3 2016-05-25 13:30:00.048 GOOG 720.92 100 720.50 720.93
4 2016-05-25 13:30:00.048 AAPL 98.00 100 NaN NaN
'''
# 我们只在报价时间和交易时间之间的10ms内,我们排除了准时的精确匹配。
# 然而,先前的数据将向前传播
pd.merge_asof(
trades,
quotes,
on="time",
by="ticker",
tolerance=pd.Timedelta("10ms"),
allow_exact_matches=False
)
'''
time ticker price quantity bid ask
0 2016-05-25 13:30:00.023 MSFT 51.95 75 NaN NaN
1 2016-05-25 13:30:00.038 MSFT 51.95 155 51.97 51.98
2 2016-05-25 13:30:00.048 GOOG 720.77 100 NaN NaN
3 2016-05-25 13:30:00.048 GOOG 720.92 100 NaN NaN
4 2016-05-25 13:30:00.048 AAPL 98.00 100 NaN NaN
'''
以下示例展示如何使用 pandas.merge_asof
函数合并两个时间序列数据集。
import pandas as pd
# 构造示例数据
data1 = pd.DataFrame({
'time': pd.to_datetime(['2023-01-01 10:00', '2023-01-01 10:05', '2023-01-01 10:10']),
'price': [100, 101, 102]
})
data2 = pd.DataFrame({
'time': pd.to_datetime(['2023-01-01 10:01', '2023-01-01 10:06']),
'volume': [200, 210]
})
print("data1:")
print(data1)
print("\ndata2:")
print(data2)
# 使用 merge_asof 进行近似合并
merged_data = pd.merge_asof(data1, data2, on='time', direction='backward')
print("\n合并后的数据:")
print(merged_data)
输出结果:
data1:
time price
0 2023-01-01 10:00:00 100
1 2023-01-01 10:05:00 101
2 2023-01-01 10:10:00 102
data2:
time volume
0 2023-01-01 10:01:00 200
1 2023-01-01 10:06:00 210
合并后的数据:
time price volume
0 2023-01-01 10:00:00 100 NaN
1 2023-01-01 10:05:00 101 200.0
2 2023-01-01 10:10:00 102 210.0
在这个例子中,pandas.merge_asof
按时间列将两个数据集进行了近似合并。由于我们选择了 'backward'
方向,数据集 data2
中每条记录被合并到最近且不晚于 data1
中对应时间点的记录。
更新时间:Aug. 14, 2024, 3:04 p.m. 标签:pandas python 合并 顺序