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字符串不是列表或嵌套字典,这不会是问题。