如何在不丢失数据点顺序的情况下将 Pandas 中的字符串列表分解为单个列表

Posted

技术标签:

【中文标题】如何在不丢失数据点顺序的情况下将 Pandas 中的字符串列表分解为单个列表【英文标题】:How to explode list of strings in Pandas to a single list without losing the order of data points 【发布时间】:2021-01-27 17:25:52 【问题描述】:

我将一些整数值存储为 Redshift 中的字符串列表(Varchar 类型),因为 Redshift 不支持 list [] data-types 。现在出于某种分析目的,我需要将字符串列表(包含整数值)转换为一维 int 数组。

样本数据:

dummy_df = pd.DataFrame('customer_id':[1,2,3],'values':[['[1]','[1,8]'],['[3,7]','[3]'],'[5]'] )
print(dummy_df)

输出数据:

final_df = pd.DataFrame('customer_id':[1,2,3],'values':[[1,1,8],[3,7,3],[5]] )
final_df

注意: DataFrame dummy_df value-column 是一个字符串列表

【问题讨论】:

【参考方案1】:

试试下面的代码(希望是不言自明的):

dummy_df['values'] = (dummy_df['values'].explode()     # flatten the list structure
                          .str.extractall('(\d+)')     # extract the digits
                          .astype(int)                 # convert to int
                          .groupby(level=0).agg(list)  # aggregate the list
                     )

print(dummy_df.to_dict('list'))

输出:

'customer_id': [1, 2, 3], 'values': [[1, 1, 8], [3, 7, 3], [5]]

【讨论】:

【参考方案2】:

一种缓慢应用的方法是将这些字符串评估为列表,然后求和。

import ast

dummy_df['values'] = dummy_df['values'].explode().apply(ast.literal_eval).sum(level=0)

   customer_id     values
0            1  [1, 1, 8]
1            2  [3, 7, 3]
2            3        [5]

无论如何,使用 pandas 进行的复杂对象操作的扩展性相当差。 @QuangHoang 的方法稍微快一点。

import perfplot
import pandas as pd
import numpy as np
import ast


def quang(df):
    return (df['values'].explode()              # flatten the list structure
               .str.extractall('(\d+)')         # extract the digits
               .astype(int)                     # convert to int
               .groupby(level=0).agg(list))[0]  # aggregate the list
           
    
def alollz(df):
    return df['values'].explode().apply(ast.literal_eval).sum(level=0)



perfplot.show(
    setup=lambda n: pd.concat([pd.DataFrame('customer_id':[1,2,3],
                                             'values':[['[1]','[1,8]'], ['[3,7]','[3]'], '[5]'])]*n,
                              ignore_index=True), 
    kernels=[
        lambda df: quang(df),
        lambda df: alollz(df),
    ],
    labels=['str.extract', 'ast.literal_eval'],
    n_range=[2 ** k for k in range(1, 16)],
    equality_check=lambda x,y: x.compare(y).empty,
    xlabel='~len(df)'
)

【讨论】:

感谢@Alollz .. 这种方法也很有效。非常感谢性能基准图 :) @ashish 是的,我希望它会比 QuangHoang 稍微快一点,但可惜应用速度很慢。但正如您所看到的,即使是内置的 pandas 字符串方法对于字符串/对象操作也相当慢。至少它的代码略少:D

以上是关于如何在不丢失数据点顺序的情况下将 Pandas 中的字符串列表分解为单个列表的主要内容,如果未能解决你的问题,请参考以下文章

如何在不丢失 Xampp 中的数据的情况下将类型从 varchar 更改为 Date

如何在不丢失 exif 数据的情况下将 UIImage 转换为 JPEG?

Python 3:如何在不保存在磁盘上的情况下将 pandas 数据帧作为 csv 流上传?

如何在不丢失小数的情况下将数据框中的字符转换为数字

如何在不丢失信息的情况下将因子转换为整数\数字?

如何在不丢失 swift 精度的情况下将 String 转换为 Double [重复]