我的 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。我会在回答中做出一些假设。他们是
- <罢工>
- 您无法控制数据,因此无法正确转义逗号。
首先,一些导入
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/