Dim*_*old 20 python join numpy pandas
我经常使用范围条件将pandas用于合并(join).
例如,如果有2个数据帧:
A(A_id,A_value)
B(B_id,B_low,B_high,B_name)
它们很大并且大小相同(比如每个2M记录).
我想在A和B之间建立一个内连接,所以A_value将在B_low和B_high之间.
使用SQL语法:
SELECT *
FROM A,B
WHERE A_value between B_low and B_high
Run Code Online (Sandbox Code Playgroud)
这将非常简单,简短而有效.
同时在pandas中唯一的方法(不使用我发现的循环)是在两个表中创建一个虚拟列,连接它(相当于交叉连接),然后过滤掉不需要的行.这听起来沉重而复杂:
A['dummy'] = 1
B['dummy'] = 1
Temp = pd.merge(A,B,on='dummy')
Result = Temp[Temp.A_value.between(Temp.B_low,Temp.B_high)]
Run Code Online (Sandbox Code Playgroud)
我的另一个解决方案是通过使用B[(x>=B.B_low) & (x<=B.B_high)]掩码在B上的每个A值上应用搜索函数,但它听起来效率低,并且可能需要索引优化.
是否有更优雅和/或更有效的方式来执行此操作?
piR*_*red 31
设置
考虑数据帧A和B
A = pd.DataFrame(dict(
A_id=range(10),
A_value=range(5, 105, 10)
))
B = pd.DataFrame(dict(
B_id=range(5),
B_low=[0, 30, 30, 46, 84],
B_high=[10, 40, 50, 54, 84]
))
A
A_id A_value
0 0 5
1 1 15
2 2 25
3 3 35
4 4 45
5 5 55
6 6 65
7 7 75
8 8 85
9 9 95
B
B_high B_id B_low
0 10 0 0
1 40 1 30
2 50 2 30
3 54 3 46
4 84 4 84
Run Code Online (Sandbox Code Playgroud)
numpy
最简单的方法是使用numpy广播.
我们寻找A_value大于或等于的每个实例,B_low同时A_value小于或等于B_high.
a = A.A_value.values
bh = B.B_high.values
bl = B.B_low.values
i, j = np.where((a[:, None] >= bl) & (a[:, None] <= bh))
pd.DataFrame(
np.column_stack([A.values[i], B.values[j]]),
columns=A.columns.append(B.columns)
)
A_id A_value B_high B_id B_low
0 0 5 10 0 0
1 3 35 40 1 30
2 3 35 50 2 30
3 4 45 50 2 30
Run Code Online (Sandbox Code Playgroud)
为了解决这些评论并给出类似于左连接的内容,我附加了A一些不匹配的内容.
pd.DataFrame(
np.column_stack([A.values[i], B.values[j]]),
columns=A.columns.append(B.columns)
).append(
A[~np.in1d(np.arange(len(A)), np.unique(i))],
ignore_index=True, sort=False
)
A_id A_value B_id B_low B_high
0 0 5 0.0 0.0 10.0
1 3 35 1.0 30.0 40.0
2 3 35 2.0 30.0 50.0
3 4 45 2.0 30.0 50.0
4 1 15 NaN NaN NaN
5 2 25 NaN NaN NaN
6 5 55 NaN NaN NaN
7 6 65 NaN NaN NaN
8 7 75 NaN NaN NaN
9 8 85 NaN NaN NaN
10 9 95 NaN NaN NaN
Run Code Online (Sandbox Code Playgroud)
不确定这是否更有效,但是您可以将 sql 直接(例如来自模块 sqlite3)与 Pandas(受此问题的启发)一起使用,例如:
conn = sqlite3.connect(":memory:")
df2 = pd.DataFrame(np.random.randn(10, 5), columns=["col1", "col2", "col3", "col4", "col5"])
df1 = pd.DataFrame(np.random.randn(10, 5), columns=["col1", "col2", "col3", "col4", "col5"])
df1.to_sql("df1", conn, index=False)
df2.to_sql("df2", conn, index=False)
qry = "SELECT * FROM df1, df2 WHERE df1.col1 > 0 and df1.col1<0.5"
tt = pd.read_sql_query(qry,conn)
Run Code Online (Sandbox Code Playgroud)
您可以根据应用程序的需要调整查询
| 归档时间: |
|
| 查看次数: |
6707 次 |
| 最近记录: |