首页 > 解决方案 > 将字符串拆分为列表并将项目转换为 int

问题描述

我有一个 pandas 数据框,其中有一列values如下:

0       16 0
1    7 1 2 0
2          5
3          1
4         18

我想要的是创建另一列,modified_values其中包含拆分每个值后我将获得的所有不同数字的列表。新列将如下所示:

0       [16, 0]
1    [7, 1, 2, 0]
2          [5]
3          [1]
4         [18]

请注意此列表中的值应该是int而不是strings

我知道的事情:

1)我可以像这样以矢量化方式拆分列 df.values.str.split(" ")。这会给我列表,但列表中的对象将是字符串。我可以像这样在上面添加另一个操作,df.values.str.split(" ").apply(func to convert values to int)但这不会被矢量化

2)我可以直接这样做df['modified_values']= df['values'].apply(func that splits as well as converts to int)

第二个肯定会比第一个慢得多,但我想知道是否可以通过矢量化方式实现相同的目标。

标签: pythonpython-3.xstringpandasnumpy

解决方案


没有原生的“矢量化”解决方案是可能的

我之所以强调这一点,是因为假设pd.Series.str方法是矢量化的,这是一个常见的错误。他们不是。它们以效率为代价提供便利和错误处理。仅对于干净的数据,例如没有NaN值,列表理解可能是您的最佳选择:

df = pd.DataFrame({'A': ['16 0', '7 1 2 0', '5', '1', '18']})

df['B'] = [list(map(int, i.split())) for i in df['A']]

print(df)

         A             B
0     16 0       [16, 0]
1  7 1 2 0  [7, 1, 2, 0]
2        5           [5]
3        1           [1]
4       18          [18]

性能基准测试

为了说明 的性能问题pd.Series.str,您可以看到对于较大的数据帧,您传递给 Pandas 的操作越多,性能下降得越多:

df = pd.concat([df]*10000)

%timeit [list(map(int, i.split())) for i in df['A']]            # 55.6 ms
%timeit [list(map(int, i)) for i in df['A'].str.split()]        # 80.2 ms
%timeit df['A'].str.split().apply(lambda x: list(map(int, x)))  # 93.6 ms

listas elements inpd.Series也是反熊猫

如此处所述,串联保存列表会提供 2 层指针,不推荐:

不要这样做。Pandas 从来没有被设计成以系列/列的形式保存列表。您可以炮制昂贵的解决方法,但不建议这样做。

不建议串联保存列表的主要原因是您失去了使用保存在连续内存块中的 NumPy 数组的矢量化功能。您的系列将是 objectdtype,它代表一系列指针,很像list. 您将失去内存和性能方面的好处,以及访问优化的 Pandas 方法。

另请参阅NumPy 与常规 Python 列表相比有哪些优势? 支持 Pandas 的论点与支持 NumPy 的论点相同。


推荐阅读