在Python中,polars将json字符串列转换为dict进行过滤



Hi有一个数据帧,其中有一个名为tags的列,它是一个json字符串。

我想在标记列上过滤这个数据帧,这样它只包含存在特定标记键或标记具有特定值的行。

我想我可以做一个字符串包含匹配,但认为首先将json转换为dict并使用has_key等可能更健壮?

在python polar中,建议使用什么方法来实现这一点?

感谢

Polars没有通用字典类型。相反,字典是作为结构导入/映射的。每个字典键都映射到一个结构"字段名称",相应的字典值成为该字段的值。

但是,创建类型结构的系列时存在一些约束。其中两个是:

  • 所有结构都必须具有相同的字段名
  • 字段名称必须按相同顺序列出

在您的描述中,您提到了has_key,这表示字典将没有相同的键。因此,从字典中创建结构的列将不起作用。(有关更多信息,您可以看到此堆栈溢出响应。(

json_path_match

我建议使用json_path_match,它基于一些简单的JSONPath语法提取值。使用JSONPath语法,您应该能够查询键是否存在,并检索其值。(对于简单的无测试字典,这些是相同的查询。(

例如,让我们从以下数据开始:

import polars as pl
json_list = [
"""{"name": "Maria",
"position": "developer",
"office": "Seattle"}""",
"""{"name": "Josh",
"position": "analyst",
"termination_date": "2020-01-01"}""",
"""{"name": "Jorge",
"position": "architect",
"office": "",
"manager_st_dt": "2020-01-01"}""",
]
df = pl.DataFrame(
{
"tags": json_list,
}
).with_row_count("id", 1)
df
shape: (3, 2)
┌─────┬────────────────────┐
│ id  ┆ tags               │
│ --- ┆ ---                │
│ u32 ┆ str                │
╞═════╪════════════════════╡
│ 1   ┆ {"name": "Maria",  │
│     ┆         "posit...  │
├╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 2   ┆ {"name": "Josh",   │
│     ┆         "positi... │
├╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 3   ┆ {"name": "Jorge",  │
│     ┆         "posit...  │
└─────┴────────────────────┘

查询值:

df.with_columns([
pl.col('tags').str.json_path_match(r"$.name").alias('name'),
pl.col('tags').str.json_path_match(r"$.office").alias('location'),
pl.col('tags').str.json_path_match(r"$.manager_st_dt").alias('manager start date'),
])
shape: (3, 5)
┌─────┬────────────────────┬───────┬──────────┬────────────────────┐
│ id  ┆ tags               ┆ name  ┆ location ┆ manager start date │
│ --- ┆ ---                ┆ ---   ┆ ---      ┆ ---                │
│ u32 ┆ str                ┆ str   ┆ str      ┆ str                │
╞═════╪════════════════════╪═══════╪══════════╪════════════════════╡
│ 1   ┆ {"name": "Maria",  ┆ Maria ┆ Seattle  ┆ null               │
│     ┆         "posit...  ┆       ┆          ┆                    │
├╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 2   ┆ {"name": "Josh",   ┆ Josh  ┆ null     ┆ null               │
│     ┆         "positi... ┆       ┆          ┆                    │
├╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 3   ┆ {"name": "Jorge",  ┆ Jorge ┆          ┆ 2020-01-01         │
│     ┆         "posit...  ┆       ┆          ┆                    │
└─────┴────────────────────┴───────┴──────────┴────────────────────┘

请注意null值。这是找不到键时的返回值。我们将把这个事实用于您提到的has_key功能。

此外,如果我们看看";位置";列中,您将看到json_path_match确实区分了空字符串"office":""和未找到的键。。

要筛选是否存在密钥,我们只需筛选null值。

df.filter(
pl.col('tags').str.json_path_match(r"$.manager_st_dt").is_not_null()
)
shape: (1, 2)
┌─────┬───────────────────┐
│ id  ┆ tags              │
│ --- ┆ ---               │
│ u32 ┆ str               │
╞═════╪═══════════════════╡
│ 3   ┆ {"name": "Jorge", │
│     ┆         "posit... │
└─────┴───────────────────┘

json_path_match也将使用嵌套结构。(有关详细信息,请参阅语法页面。(

但是,有一个限制:json_path_match将只返回查询的第一个匹配项,而不是匹配项列表。如果您的JSON字符串不是列表或嵌套字典,这不会是问题。

最新更新