在极坐标中创建一个新列,将函数应用于列

问题描述 投票:0回答:2

我有以下用于操作不起作用的极坐标数据框的代码

import polars as pl
import xml.etree.ElementTree as ET

# create a sample dataframe
df = pl.DataFrame({
    'A': [1, 2, 3],
    'B': ['<p>some text</p><p>bla</p>', '<p>some text<p><p>foo</p>', '<p>some text<p>']
})

def func(mystring):
    return mystring*2

def func2(xml_string):
    root = ET.fromstring(xml_string)
    text_list = []
    for elem in root.iter():
        text = elem.text.strip() if elem.text else ''
        text_list.append(text)
    return test_list

# create a sample series to add as a new column
df = df.with_columns((pl.col("A").map_batches(lambda x: func(x)).alias('new_col')))
df = df.with_columns((pl.col("B").map_batches(lambda x: func2(x)).alias('new_col2')))

print(df)

添加列的第一行有效,即添加 new_col

但是第二个不起作用。

我得到的错误是:

计算错误:类型错误:需要类似字节的对象,而不是“系列”

基本上,我的用例是包含 XML 字符串的列,我必须对其进行操作,创建 XML 对象并提取信息。

我该如何继续?

python xml apply python-polars
2个回答
2
投票

您的第一个示例之所以有效,是因为

*2
是矢量化的。

例如,如果你这样做

func(pl.Series([1,2,3,4,5]))

然后你会得到一系列原始乘以 2 的值。

您的

func2
未矢量化。要使用
map
,那么您的函数需要对整个列进行操作并返回类似系列的内容。

例如:

from lxml import etree as ET
def func2_series(xml_strings):
    ret_List=[]
    for xml_string in xml_strings:
        root = ET.fromstring(xml_string, ET.XMLParser(recover=True))
        text_list = []
        for elem in root.iter():
            text = elem.text.strip() if elem.text else ''
            text_list.append(text)
        ret_List.append(text_list)
    return pl.Series(ret_List)

随后

dfpl.with_columns(pl.col("B").map(func2_series).alias('new_col2'))

会起作用的。

如果你有的话

def func2(xml_string):
    root = ET.fromstring(xml_string, ET.XMLParser(recover=True))
    text_list = []
    for elem in root.iter():
        text = elem.text.strip() if elem.text else ''
        text_list.append(text)
    return text_list

然后你可以使用 apply,然后 Polars 会为你做循环。

dfpl.with_columns(pl.col("B").apply(func2))

顺便说一句,如果您传递的函数接受您所拥有的确切

x
,则不需要使用 lambda。换句话说,只要你有
.map(lambda x: func2(x))
,你就可以做
.map(func2)
。如果您需要转换参数,那么 lambda 就会发挥作用。


1
投票

如评论中所述,使用

.apply
而不是
.map
。另外,如果您只想要字符串列表,我建议使用
beautifulsoup
s 方法
.stripped_strings
:

import polars as pl
from bs4 import BeautifulSoup

# create a sample dataframe
dfpl = pl.DataFrame({
    'A': [1, 2, 3],
    'B': ['<p>some text</p><p>bla</p>', '<p>some text<p><p>foo</p>', '<p>some text<p>']
})

def func(mystring):
    return mystring*2

def func2(xml_string):
    soup = BeautifulSoup(xml_string, 'html.parser')
    return list(soup.stripped_strings)

# create a sample series to add as a new column
dfpl=dfpl.with_columns([(pl.col("A").apply(lambda x: func(x)).alias('new_col'))])
dfpl=dfpl.with_columns([(pl.col("B").apply(lambda x: func2(x)).alias('new_col2'))])

print(dfpl)

打印:

shape: (3, 4)
┌─────┬────────────────────────────┬─────────┬──────────────────────┐
│ A   ┆ B                          ┆ new_col ┆ new_col2             │
│ --- ┆ ---                        ┆ ---     ┆ ---                  │
│ i64 ┆ str                        ┆ i64     ┆ list[str]            │
╞═════╪════════════════════════════╪═════════╪══════════════════════╡
│ 1   ┆ <p>some text</p><p>bla</p> ┆ 2       ┆ ["some text", "bla"] │
│ 2   ┆ <p>some text<p><p>foo</p>  ┆ 4       ┆ ["some text", "foo"] │
│ 3   ┆ <p>some text<p>            ┆ 6       ┆ ["some text"]        │
└─────┴────────────────────────────┴─────────┴──────────────────────┘
© www.soinside.com 2019 - 2024. All rights reserved.