gpt4 book ai didi

python - 如何根据非简单标准执行 DataFrames 与 Pandas 的内部或外部连接

转载 作者:太空狗 更新时间:2023-10-29 23:59:44 25 4
gpt4 key购买 nike

给定如下两个数据框:

>>> import pandas as pd

>>> df_a = pd.DataFrame([{"a": 1, "b": 4}, {"a": 2, "b": 5}, {"a": 3, "b": 6}])
>>> df_b = pd.DataFrame([{"c": 2, "d": 7}, {"c": 3, "d": 8}])
>>> df_a
a b
0 1 4
1 2 5
2 3 6

>>> df_b
c d
0 2 7
1 3 8

我们想使用非简单化的标准生成两个数据帧的 SQL 样式连接,比方说“df_b.c > df_a.a”。据我所知,虽然 merge() 肯定是解决方案的一部分,但我不能直接使用它,因为它不接受“ON”条件的任意表达式(除非我遗漏了什么东西?)。

在 SQL 中,结果如下所示:

# inner join
sqlite> select * from df_a join df_b on c > a;
1|4|2|7
1|4|3|8
2|5|3|8

# outer join
sqlite> select * from df_a left outer join df_b on c > a;
1|4|2|7
1|4|3|8
2|5|3|8
3|6||

我目前的内连接方法是生成笛卡尔积df_a 和 df_b,通过向两者添加一列“1”,然后使用在“1”列上合并(),然后应用“c > a”标准。

>>> import numpy as np
>>> df_a['ones'] = np.ones(3)
>>> df_b['ones'] = np.ones(2)
>>> cartesian = pd.merge(df_a, df_b, left_on='ones', right_on='ones')
>>> cartesian
a b ones c d
0 1 4 1 2 7
1 1 4 1 3 8
2 2 5 1 2 7
3 2 5 1 3 8
4 3 6 1 2 7
5 3 6 1 3 8
>>> cartesian[cartesian.c > cartesian.a]
a b ones c d
0 1 4 1 2 7
1 1 4 1 3 8
3 2 5 1 3 8

对于外部连接,到目前为止我不确定最好的方法我一直在玩弄内部连接,然后应用否定获取所有其他行的条件,然后尝试对其进行编辑“否定”设置到原来的,但它并没有真正起作用。

编辑。 HYRY 在这里回答了具体问题,但我需要 Pandas API 中更通用和更多的东西,因为我的连接标准可以是任何东西,而不仅仅是那个比较。对于外部连接,首先我在“左侧”添加了一个额外的索引,它将在我执行内部连接后自行维护:

df_a['_left_index'] = df_a.index

然后我们做笛卡尔并得到内连接:

cartesian = pd.merge(df_a, df_b, left_on='ones', right_on='ones')
innerjoin = cartesian[cartesian.c > cartesian.a]

然后我在“df_a”中获取我们需要的额外索引 ID,并从“df_a”中获取行:

remaining_left_ids = set(df_a['_left_index']).\
difference(innerjoin['_left_index'])
remaining = df_a.ix[remaining_left_ids]

然后我们使用直接的 concat(),它将缺失的列替换为左侧的“NaN”(我认为它之前没有这样做,但我猜是这样做的):

outerjoin = pd.concat([innerjoin, remaining]).reset_index()

HYRY 的想法是只对我们需要比较的列进行笛卡尔坐标计算,这基本上是正确的答案,尽管在我的具体情况下,实现起来可能有点棘手(一般化和全部)。

问题:

  1. 如何在“c > a”上生成 df_1 和 df_2 的“连接”?将你做同样的“笛卡尔积,过滤器”方法还是有更好的方法怎么办?

  2. 如何生成相同的“左外连接”?

最佳答案

我用ufunc的外层方法计算结果,例子如下:

首先,一些数据:

import pandas as pd
import numpy as np
df_a = pd.DataFrame([{"a": 1, "b": 4}, {"a": 2, "b": 5}, {"a": 3, "b": 6}, {"a": 4, "b": 8}, {"a": 1, "b": 7}])
df_b = pd.DataFrame([{"c": 2, "d": 7}, {"c": 3, "d": 8}, {"c": 2, "d": 10}])
print "df_a"
print df_a
print "df_b"
print df_b

输出:

df_a
a b
0 1 4
1 2 5
2 3 6
3 4 8
4 1 7
df_b
c d
0 2 7
1 3 8
2 2 10

Inner join,因为只计算c & a的笛卡尔积,内存占用小于整个DataFrame的笛卡尔积:

ia, ib = np.where(np.less.outer(df_a.a, df_b.c))
print pd.concat((df_a.take(ia).reset_index(drop=True),
df_b.take(ib).reset_index(drop=True)), axis=1)

输出:

   a  b  c   d
0 1 4 2 7
1 1 4 3 8
2 1 4 2 10
3 2 5 3 8
4 1 7 2 7
5 1 7 3 8
6 1 7 2 10

要计算左外连接,请使用 numpy.setdiff1d() 查找 df_a 中不在内连接中的所有行:

na = np.setdiff1d(np.arange(len(df_a)), ia)
nb = -1 * np.ones_like(na)
oa = np.concatenate((ia, na))
ob = np.concatenate((ib, nb))
print pd.concat([df_a.take(oa).reset_index(drop=True),
df_b.take(ob).reset_index(drop=True)], axis=1)

输出:

   a  b   c   d
0 1 4 2 7
1 1 4 3 8
2 1 4 2 10
3 2 5 3 8
4 1 7 2 7
5 1 7 3 8
6 1 7 2 10
7 3 6 NaN NaN
8 4 8 NaN NaN

关于python - 如何根据非简单标准执行 DataFrames 与 Pandas 的内部或外部连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15581829/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com