python - 如何从 Pandas 数据框中的字典中删除大括号、撇号和方括号 (Python)

标签 python regex pandas

我的 csv 文件中有以下数据:

from StringIO import StringIO
import pandas as pd

the_data = """
ABC,2016-6-9 0:00,95,{'//PurpleCar': [115L], '//YellowCar': [403L], '//BlueCar': [16L], '//WhiteCar-XYZ': [0L]}
ABC,2016-6-10 0:00,0,{'//PurpleCar': [219L], '//YellowCar': [381L], '//BlueCar': [90L], '//WhiteCar-XYZ': [0L]}
ABC,2016-6-11 0:00,0,{'//PurpleCar': [817L], '//YellowCar': [21L], '//BlueCar': [31L], '//WhiteCar-XYZ': [0L]}
ABC,2016-6-12 0:00,0,{'//PurpleCar': [80L], '//YellowCar': [2011L], '//BlueCar': [8888L], '//WhiteCar-XYZ': [0L]}
ABC,2016-6-13 0:00,0,{'//PurpleCar': [32L], '//YellowCar': [15L], '//BlueCar': [4L], '//WhiteCar-XYZ': [0L]}
DEF,2016-6-16 0:00,0,{'//PurpleCar': [32L], '//BlackCar': [15L], '//PinkCar': [4L], '//NPO-GreenCar': [0L]}
DEF,2016-6-17 0:00,0,{'//PurpleCar': [32L], '//BlackCar': [15L], '//PinkCar': [4L], '//NPO-GreenCar': [0L]}
DEF,2016-6-18 0:00,0,{'//PurpleCar': [32L], '//BlackCar': [15L], '//PinkCar': [4L], '//NPO-GreenCar': [0L]}
DEF,2016-6-19 0:00,0,{'//PurpleCar': [32L], '//BlackCar': [15L], '//PinkCar': [4L], '//NPO-GreenCar': [0L]}
DEF,2016-6-20 0:00,0,{'//PurpleCar': [32L], '//BlackCar': [15L], '//PinkCar': [4L], '//NPO-GreenCar': [0L]}
"""

我将文件读取到 Pandas 数据框中,如下所示:

df = pd.read_csv(StringIO(the_data), sep=',')

然后,我添加一些列标题,如下所示:

df.columns = ['Company',
                    'Date',
                    'Volume',
                    'Car1',
                    'Car2',
                    'Car3',
                    'Car4']

我看到数据如下:

ABC,2016-6-9 0:00,95,{'//PurpleCar': [115L], '//YellowCar': [403L], '//BlueCar': [16L], '//WhiteCar-XYZ': [0L]

但是,我希望查看以下任何内容的数据:

a) 字典开头的大括号 ("{") 和结尾的大括号 ("}")

b) 数值后面的“L”

c) 方括号("[""]")包围数值

d) 按键周围的撇号

理想情况下,数据将按如下方式转换:

ABC,2016-6-9 0:00,95,//PurpleCar: 115, //YellowCar: 403, //BlueCar: 16, //WhiteCar-XYZ: 0

我尝试过这个:

df['Car1'] = df['Car1'].str.strip(['{', '}', '[', 'L]'])

但是,这不起作用。它会导致“Car1”列变为 NaN 值。

是否可以转换数据帧,使数据帧的每一行读取如下?

ABC,2016-6-9 0:00,95,//PurpleCar: 115, //YellowCar: 403, //BlueCar: 16, //WhiteCar-XYZ: 0

谢谢!

更新:

使用以下正则表达式:

df['Car1'] = df['Car1'].str.replace(r'\D+', '').astype('int')

结果如下:

ABC,2016-6-9 0:00,95, 115 , //YellowCar: 403, //BlueCar: 16, //WhiteCar-XYZ: 0

我们丢失了“//PurpleCar”,只剩下数值 115。这是一个好的开始,但如果我们也能看到“//PurpleCar”键,那就太好了。

有什么想法吗?

<小时/>

更新2:

根据 piRSquared 和 HYRY 的评论,我的目标是能够绘制数值结果。因此,我希望数据框如下所示:

   Company   Date            PurpleCar  YellowCar   BlueCar     WhiteCar      

0  ABC       2016-6-9 0:00   115        403         16          0
1  ABC       2016-6-10 0:00  219        381         90          0
2  ABC       2016-6-11 0:00  817        21          31          0
3  ABC       2016-6-12 0:00  80         2011        8888        0
4  ABC       2016-6-13 0:00  32         15          4           0
5  DEF       2016-6-16 0:00  32         15          4           0
6  DEF       2016-6-17 0:00  32         15          4           0
7  DEF       2016-6-18 0:00  32         15          4           0
8  DEF       2016-6-19 0:00  32         15          4           0
9  DEF       2016-6-20 0:00  32         15          4           0

*更新3:*

最初发布的数据有一个小错误。数据如下:

the_data = """
ABC,2016-6-9 0:00,95,"{'//Purple': [115L], '//Yellow': [403L], '//Blue': [16L], '//White-XYZ': [0L]}"
ABC,2016-6-10 0:00,0,"{'//Purple': [219L], '//Yellow': [381L], '//Blue': [90L], '//White-XYZ': [0L]}"
ABC,2016-6-11 0:00,0,"{'//Purple': [817L], '//Yellow': [21L], '//Blue': [31L], '//White-XYZ': [0L]}"
ABC,2016-6-12 0:00,0,"{'//Purple': [80L], '//Yellow': [2011L], '//Blue': [8888L], '//White-XYZ': [0L]}"
ABC,2016-6-13 0:00,0,"{'//Purple': [32L], '//Yellow': [15L], '//Blue': [4L], '//White-XYZ': [0L]}"
DEF,2016-6-16 0:00,0,"{'//Purple': [32L], '//Black': [15L], '//Pink': [4L], '//NPO-Green': [3L]}"
DEF,2016-6-17 0:00,0,"{'//Purple': [32L], '//Black': [15L], '//Pink': [4L], '//NPO-Green': [0L]}"
DEF,2016-6-18 0:00,0,"{'//Purple': [32L], '//Black': [15L], '//Pink': [4L], '//NPO-Green': [7L]}"
DEF,2016-6-19 0:00,0,"{'//Purple': [32L], '//Black': [15L], '//Pink': [4L], '//NPO-Green': [14L]}"
DEF,2016-6-20 0:00,0,"{'//Purple': [32L], '//Black': [15L], '//Pink': [4L], '//NPO-Green': [21L]}"
"""

此数据与原始数据之间的区别在于左大括号 ("{") 之前和右大括号 (“}”)。

最佳答案

编辑:该文件似乎实际上是转义的 CSV,因此我们不需要对此部分进行自定义解析。

正如 @Blckknght 在评论中指出的那样,该文件不是有效的 CSV。我会在回答中做出一些假设。他们是

    <罢工>
  1. 您无法控制数据,因此无法正确转义逗号。
  2. 前三列不包含任何逗号。
  3. 第三列遵循 python 字典的语法。
  4. 列表中始终有一个值位于字典值中。

首先,一些导入

import ast
import pandas as pd

我们只需用逗号分隔行,因为我们不需要处理任何类型的 CSV 转义(假设 #1 和 #2)。

rows = (line.split(",", 3) for line in the_data.splitlines() if line.strip() != "")

fixed_columns = pd.DataFrame.from_records(rows, columns=["Company", "Date", "Value", "Cars_str"])

<罢工>

fixed_columns = pd.read_csv(..., names=["Company", "Date", "Value", "Cars_str"])

前三列是固定的,我们保持原样。我们可以用 ast.literal_eval 解析最后一列因为它是dict (假设#3)。如果格式发生变化,这比正则表达式更具可读性和更灵活。此外,您还会更早地检测到格式更改。

cars = fixed_columns["Cars_str"].apply(ast.literal_eval)
del fixed_columns["Cars_str"]

这部分的答案相当your other question .

我们准备函数来处理字典的键和值,这样如果我们对字典内容的假设失败,它们就会失败。

def get_single_item(list_that_always_has_single_item):
    v, = list_that_always_has_single_item
    return v

def extract_car_name(car_str):
    assert car_str.startswith("//"), car_str
    return car_str[2:]

我们应用函数并构造pd.Series这使我们能够...

dynamic_columns = cars.apply(
    lambda x: pd.Series({
            extract_car_name(k): get_single_item(v) 
            for k, v in x.items()
    }))    

...将列添加到数据框

result = pd.concat([fixed_columns, dynamic_columns], axis=1)
result

最后,我们得到了表格:

  Company            Date Value  BlackCar  BlueCar  NPO-GreenCar  PinkCar  \
0     ABC   2016-6-9 0:00    95       NaN     16.0           NaN      NaN   
1     ABC  2016-6-10 0:00     0       NaN     90.0           NaN      NaN   
2     ABC  2016-6-11 0:00     0       NaN     31.0           NaN      NaN   
3     ABC  2016-6-12 0:00     0       NaN   8888.0           NaN      NaN   
4     ABC  2016-6-13 0:00     0       NaN      4.0           NaN      NaN   
5     DEF  2016-6-16 0:00     0      15.0      NaN           0.0      4.0   
6     DEF  2016-6-17 0:00     0      15.0      NaN           0.0      4.0   
7     DEF  2016-6-18 0:00     0      15.0      NaN           0.0      4.0   
8     DEF  2016-6-19 0:00     0      15.0      NaN           0.0      4.0   
9     DEF  2016-6-20 0:00     0      15.0      NaN           0.0      4.0   

   PurpleCar  WhiteCar-XYZ  YellowCar  
0      115.0           0.0      403.0  
1      219.0           0.0      381.0  
2      817.0           0.0       21.0  
3       80.0           0.0     2011.0  
4       32.0           0.0       15.0  
5       32.0           NaN        NaN  
6       32.0           NaN        NaN  
7       32.0           NaN        NaN  
8       32.0           NaN        NaN  
9       32.0           NaN        NaN  

关于python - 如何从 Pandas 数据框中的字典中删除大括号、撇号和方括号 (Python),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39928273/

相关文章:

python - django 服务 : wsgi. py? 'cannot be loaded as Python module'

python - 如何在 Python 中抑制 OpenAI API 警告

c - C中http header 的正则表达式

Python - 一种学习和检测文本模式的方法?

多处理中共享dict()中的python共享Queue()

javascript - ASPX 形式的错误消息和验证数据

python - Pandas 损益汇总至下一个工作日

python - 根据现有单元格下的值创建新列

python - Pandas 通过保留一列的第一个元素和另一列的最后一个元素来合并

python - 需要一些关于如何实现基于 golang 的 restful api 应用程序的帮助