我在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]}"
"""
此数据与原始数据之间的差异是在开始大括号((")
)之前和结束大括号("{"
之后)的撇号"}"
。
答案 0 :(得分:1)
修改:该文件似乎实际上是转发的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)。如果格式改变比正则表达式,这是IMO更可读和更灵活。您也可以提前检测格式更改。
cars = fixed_columns["Cars_str"].apply(ast.literal_eval)
del fixed_columns["Cars_str"]
这部分回答your other question。
我们准备函数来处理dict的键和值,这样如果我们对dict内容的假设失败,它们就会失败。
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
答案 1 :(得分:0)
答案 2 :(得分:0)
我认为最好将字符串转换为两列:
from io import StringIO
import pandas as pd
df = pd.read_csv(StringIO(the_data), sep=',', header=None)
df.columns = ['Company','Date','Volume','Car1','Car2','Car3','Car4']
cars = ["Car1", "Car2", "Car3", "Car4"]
pattern = r"//(?P<color>.+?)':.*?(?P<value>\d+)"
df2 = pd.concat([df[col].str
.extract(pattern)
.assign(value=lambda self: pd.to_numeric(self["value"]))
for col in cars],
axis=1, keys=cars)
结果:
Car1 Car2 Car3 Car4
color value color value color value color value
0 PurpleCar 115 YellowCar 403 BlueCar 16 WhiteCar-XYZ 0
1 PurpleCar 219 YellowCar 381 BlueCar 90 WhiteCar-XYZ 0
2 PurpleCar 817 YellowCar 21 BlueCar 31 WhiteCar-XYZ 0
3 PurpleCar 80 YellowCar 2011 BlueCar 8888 WhiteCar-XYZ 0
4 PurpleCar 32 YellowCar 15 BlueCar 4 WhiteCar-XYZ 0
5 PurpleCar 32 BlackCar 15 PinkCar 4 NPO-GreenCar 0
6 PurpleCar 32 BlackCar 15 PinkCar 4 NPO-GreenCar 0
7 PurpleCar 32 BlackCar 15 PinkCar 4 NPO-GreenCar 0
8 PurpleCar 32 BlackCar 15 PinkCar 4 NPO-GreenCar 0
9 PurpleCar 32 BlackCar 15 PinkCar 4 NPO-GreenCar 0