文档章节

从 ES|QL 到 Python 中的原生 Pandas 数据帧

elasticstack
 elasticstack
发布于 2024/10/08 16:38
字数 1227
阅读 107
收藏 0

作者:来自 Elastic Quentin Pradet

自 Elasticsearch 8.15 或 Elasticsearch Serverless 以来,ES|QL 响应支持 Apache Arrow 流式传输格式。这篇博文将向你展示如何在 Python 中利用它。在之前的一篇博文中,我演示了如何使用 CSV 作为中间表示将 ES|QL 查询转换为 Pandas 数据帧。不幸的是,CSV 需要显式类型声明,速度很慢(尤其是对于较大的数据集),并且不处理嵌套数组和对象。Apache Arrow 消除了所有这些限制。

ES|QL 到 Python 中的 Pandas 数据帧

导入测试数据

首先,让我们导入一些测试数据。和以前一样,我们将使用 employees 样本数据映射。加载此数据集的最简单方法是在 Kibana 控制台中运行这两个 Elasticsearch API 请求

将数据集转换为 Pandas DataFrame 对象

好的,解决了这个问题后,让我们使用 ES|QL Arrow 导出将完整的 employees 数据集转换为 Pandas DataFrame 对象:

from elasticsearch import Elasticsearch

client = Elasticsearch(
    "https://[host].elastic-cloud.com",
    api_key="...",
)

response = client.esql.query(
    query="FROM employees | DROP is_rehired,job_positions,salary_change* | LIMIT 500",
    format="arrow",
)
df = response.to_pandas()
print(df)

尽管此数据集仅包含 100 条记录,但我们仍使用 LIMIT 命令来避免 ES|QL 警告我们可能缺少记录。这将打印以下数据框:

    avg_worked_seconds birth_date  emp_no  ...    last_name salary  still_hired
0            268728049 1953-09-02   10001  ...      Facello  57305         True
1            328922887 1964-06-02   10002  ...       Simmel  56371         True
2            200296405 1959-12-03   10003  ...      Bamford  61805        False
3            311267831 1954-05-01   10004  ...      Koblick  36174         True
4            244294991 1955-01-21   10005  ...     Maliniak  63528         True
..                 ...        ...     ...  ...          ...    ...          ...
95           204381503 1954-09-16   10096  ...      Mandell  43889        False
96           206258084 1952-02-27   10097  ...  Waschkowski  71165        False
97           272392146 1961-09-23   10098  ...    Servieres  44817        False
98           377713748 1956-05-25   10099  ...      Sullins  73578         True
99           223910853 1953-04-21   10100  ...    Haraldson  68431         True

[100 rows x 17 columns]

好的,那么这里到底发生了什么?

  • 给定 format="arrow",Elasticsearch 返回二进制 Arrow 流数据
  • Elasticsearch Python 客户端查看 Content-Type header 并创建 PyArrow 对象
  • 最后,PyArrow 的 Pandas 集成将 PyArrow 对象转换为 Pandas 数据帧。(请注意,在大多数情况下,这不是零拷贝转换。)

这意味着要使此示例正常工作,需要安装 Pandas 和 PyArrow 可选依赖项。请注意,Pandas 本身不是严格必需的,只有 PyArrow 是必需的。如果你想改用 Polars,可以使用 from_arrow 从客户端返回的 PyArrow 表中创建 Polars 数据框。

一个限制是 Elasticsearch 目前不处理多值字段,这就是我们不得不删除 is_rehired、job_positions 和 salary_change 列的原因。此限制将在 Elasticsearch 的未来版本中取消。

无论如何,你现在有一个 Pandas 数据帧,你可以使用它来进一步分析数据。但是你也可以继续使用 ES|QL 处理数据,这在查询返回超过 10,000 行(ES|QL 查询当前可以返回的最大行数)时特别有用。

更复杂的查询

在下一个示例中,我们使用 STATS ... BY(与 SQL 中的 GROUP BY 类似)计算有多少员工讲某种语言。然后我们使用 SORT 对 languages 列的结果进行排序:

response = client.esql.query(
    query="""
    FROM employees
    | DROP is_rehired,job_positions,salary_change*
    | STATS count = COUNT(emp_no) BY languages
    | SORT languages
    | LIMIT 500
    """,
    format="arrow",
)

df = response.to_pandas()
print(df)

与 CSV 不同,我们不必指定任何类型,因为 Arrow 数据已经包含类型。结果如下:

   count  languages
0     15        1.0
1     19        2.0
2     17        3.0
3     18        4.0
4     21        5.0
5     10        NaN

21 名员工讲 5 种语言,哇!

带参数的查询

最后,假设你想要扩展上一节中的查询以仅考虑会说 N 种或更多语言的员工,其中 N 是可变参数。为此,我们可以使用 ES|QL 内置的参数支持,这消除了手动组装带有可变部分的查询所带来的注入攻击风险:

response = client.esql.query(
    query="""
    FROM employees
    | DROP is_rehired,job_positions,salary_change*
    | STATS count = COUNT(emp_no) BY languages
    | WHERE languages >= (?)
    | SORT languages
    | LIMIT 500
    """,
    format="arrow",
    params=[3],
)

df = response.to_pandas()
print(df)

打印内容如下:

   count  languages
0     17          3
1     18          4
2     21          5

结论

正如我们所见,ES|QL 的原生 Arrow 支持使得使用 Pandas 和其他 DataFrame 库比使用 CSV 更加方便,并且随着时间的推移,它将不断改进,未来版本的 Elasticsearch 将提供多值支持。

其他资源

如果你想了解有关 ES|QL 的更多信息,ES|QL 文档是最好的起点。你还可以查看使用波士顿凯尔特人队数据的其他 Python 示例。要了解有关 Python Elasticsearch 客户端本身的更多信息,你可以参考文档,在讨论中使用 language-clients 标签提问,或者在发现错误或有功能请求时提交新问题。谢谢!

准备好自己尝试一下了吗?开始免费试用
Elasticsearch 集成了 LangChain、Cohere 等工具。加入我们的高级语义搜索网络研讨会,构建你的下一个 GenAI 应用程序!

原文:From ES|QL to native Pandas dataframes in Python — Search Labs

elasticstack
粉丝 15
博文 270
码字总数 761067
作品 0
其它
私信
加载中
点击引领话题?
{{formatHtml(o.title)}}

{{i}}-{{formatHtml(o.content)}}

{{o.author.name}}
{{o.pubDate | formatDate}}
{{o.viewCount | bigNumberTransform}}
{{o.replyCount | bigNumberTransform}}

暂无文章

便宜云服务器
登录后可查看更多优质内容
返回顶部
顶部
http://www.vxiaotou.com