pandas增强—数据表的非等式连接和条件连接

Pandas 支持 equi-join,其中 join 中涉及的键被认为是相等的。这是通过 merge 和 join 函数实现的。但是,在某些情况下,所涉及的Key可能不相等;联接中还涉及一些其他逻辑条件、这称为非等式连接或不等式连接或者条件连接。

这种情况下使用pandas来的话得可以从以下2个方面着手。
1、先建立笛卡尔连接然后筛选。缺点是性能很差。
2、对于时间序列可以使用asof来连接。缺点是功能受限,不是所有的条件筛选都能用asof,特别是非时间序列的情况下。

解决方案
1、使用DuckDB 的 SQL 查询 DataFrame,性能极高。
2、使用pandas的功能增强库pyjanitor 库的 conditional_join 函数,既节省内存又不损性能;

解决方案一:
由于DuckDB是一个比较火热的项目已经成为的Python数据库。考虑到性能和代码的维护主要推荐这种方式
映入DuckDB的python库,拼接字符串为SQL语句,然后查询。
解决方案二:
该方案的有优点是代码和pandas高度兼容,如果只做简单的不等连接可以使用,复杂的条件还需要DuckDB。
可以参考下面的文章。这篇文章的主要价值在于描述了条件筛选的主要用法,相比与使用pyjanitor 我更倾向于使用DuckDB库的SQL方法。
https://samukweku.github.io/data-wrangling-blog/notebooks/Fast-and-Efficient-Inequality-Joins-in-Pandas.html
为了避免外网站打不开我接了图。在这里插入图片描述

对于使用到的pyjanitor 库,它是一个从R迁移来的python库,主要有以下3方面的功能
https://pyjanitor-devs.github.io/pyjanitor/api/io/
1、条件连接、不等式连接conditional_join。主要功能
2、对pandas读取csv和excel在功能上的增强,如一次读取多个sheet的excelAPI :xlsx_table(path, sheetname, table=None),读取多个csv等 API:read_csvs(files_path, separate_df=False, **kwargs)。次要功能,这些功能在pandas也较为容易实现,没必要多引入库和API。
3、数据清洗。主要是对空值、列的增删的处理,和各个行业(如金融)等封装的清洗方法。个人认为用处不大,提供的功能多数pandas都能实现,还得多记API。
4、其他可能有用的功能
https://www.cnblogs.com/feffery/p/15998079.html

利用also()方法穿插执行任意函数#
 pyjanitor中的also()方法允许在pandas链式过程中随意插入执行任意函数,接受上一步状态的数据框运算结果,且不影响对下一步处理逻辑的数据输入,我非常喜欢这个功能,下面是一个简单的例子:

df = (
    # 构造示例数据框
    pd.DataFrame({"a": [1, 2, 3], "b": list("abc")})
    .query("a > 1")
    # 利用also()插入lambda函数接受上一步的输入对象
    .also(lambda df: print(f"a字段<=1的记录有{df.query('a <= 1').shape[0]}行"))
    .rename(columns={'a': 'new_a'})
    # 利用also()实现中间计算结果的导出
    .also(lambda df: df.to_csv("temp.csv", index=False))
    # 利用also()打印到这一步时数据框计算结果的字段名
    .also(
        lambda df: print(f"字段名:{df.columns.tolist()}")
    )
    .drop(columns='b')
)

2、利用case_when()方法实现多条件分支#
  pyjanitor中的case_when()方法可以帮助我们针对数据框实现类似SQL中的的多条件分支运算,注意,因为是多条件分支,所以包含最后的“其他”条件在内,需要至少定义3条分支规则,参考下面的例子:

df = pd.DataFrame(
{
“a”: [0, 0, 1, 2],
“b”: [0, 3, 4, 5],
“c”: [6, 7, 8, 9],
}
)

df.case_when(
((df.a == 0) & (df.b == 0)), ‘类别1’,
((df.a == 0) & (df.b != 0)), ‘类别2’,
# 其他情况
‘类别3’,
column_name=“类别”,
)

3、利用move()方法快捷完成字段位置调整
  pyjanitor中的move()方法用于快捷调整某行或某列数据的位置,通过source参数指定需要移动的数据行index或列的字段名,target参数用于指定移动的目标位置数据行index或列的字段名,position用于设置移动方式('before’表示移动到目标之前一个位置,after表示后一个位置),axis用于设定移动方式(0表示行移动,1表示列移动)。

以最常用的列移动为例:

df = pd.DataFrame({"a": [2, 4, 6],"b": [1, 3, 5],"c": [7, 8, 9]})

在这里插入图片描述

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风暴之零

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值