Python 使用JSON功能读取CSV
我试图阅读一个包含JSON特性的大型CSV(位置在这里)。对于第一个,例如100行,文件如下所示:Python 使用JSON功能读取CSV,python,json,pandas,Python,Json,Pandas,我试图阅读一个包含JSON特性的大型CSV(位置在这里)。对于第一个,例如100行,文件如下所示: Time,location,labelA,labelB 2019-09-10,{"lng":12.9,"alt":413.0,"time":"2019-09-10","error":7.0,"lat":17.8},nan,nan 我随后分析了location列。该解决方案基本上
Time,location,labelA,labelB
2019-09-10,{"lng":12.9,"alt":413.0,"time":"2019-09-10","error":7.0,"lat":17.8},nan,nan
我随后分析了location列。该解决方案基本上将辅助对象定义为:
def CustomParser(data):
import json
j1 = json.loads(data)
return j1
然后
df=pd.read_csv('data.csv', nrows=100,converters={'location':CustomParser},header=0)
我得到以下与JSON格式相关的错误:
JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Q1:如何将功能位置解析到新列上
Q2(对于一般情况):对于数据中的nrows>100,最后的功能(labelA和labelB)也具有具有不同键和值的JSON格式。如何通过解析包含JSON(甚至部分)的每个功能来读取整个CSV?这里的问题是
JSON
字符串中的逗号被视为分隔符。您应该修改输入数据(如果您无法直接访问该文件,则始终可以先使用open
将内容读入字符串列表)
以下是一些您可以尝试的修改选项:
选项1:Quotejson
带单引号的字符串
使用单个引号(或数据中未显示的其他字符)作为json
字符串的引号字符
>cat data.csv
时间,地点,标签,标签
2019-09-10,{“lng”:12.9,“alt”:413.0,“时间”:“2019-09-10”,“错误”:7.0,“lat”:17.8}”,南,南
然后在读取数据时使用quotechar=“”
:
import pandas as pd
import json
df=pd.read_csv('data.csv', converters={'location':json.loads}, header=0, quotechar="'")
选项2:Quotejson
带双引号和转义符的字符串
如果不能使用单引号,您实际上可以使用双引号作为quotechar
,只要您转义json
字符串中的引号:
>cat data.csv
时间,地点,标签,标签
2019-09-10,“{”“lng”“:12.9”“alt”“:413.0”“time”“:”“2019-09-10”“error”“:7.0”“lat”“:17.8}”,nan,nan
请注意,这现在与您链接的问题的格式匹配
df=pd.read_csv('data.csv', converters={'location':json.loads}, header=0, quotechar='"')
选项3:更改分隔符
使用不同的字符,例如|
作为分隔符
>cat data.csv
时间|地点|标签|标签B
2019-09-10 |{“lng”:12.9,“alt”:413.0,“时间”:“2019-09-10”,“错误”:7.0,“lat”:17.8}|
现在使用sep
参数指定新的分隔符:
df=pd.read_csv('data.csv', converters={'location':json.loads}, header=0, sep="|")
每种方法都会产生相同的输出:
print(df)
# Time location labelA labelB
#0 2019-09-10 {u'lat': 17.8, u'lng': 12.9, u'error': 7.0, u'... NaN NaN
完成后,可以使用中描述的方法之一展开位置
列
修复该文件:
- 不幸的是,文件很难读取,因为每一行都包含一个
,其dict
对用逗号分隔键值
- 解决此问题的最简单方法是将每个
外部的分隔符从dict
更改为,
|
- 以下代码将读取现有文件
- 它假定第一行是标题,使用
.replace(',','|')
- 其余行将使用正则表达式替换
之外的,
{}
- 每一行都将写入一个新文件
- 它假定第一行是标题,使用
时间、位置、标签、标签
2019-09-10,{“lng”:12.9,“alt”:413.0,“time”:“2019-09-10”,“error”:7.0,“lat”:17.8},{“ack”:123,“bar”:456},{“foo”:123,“bar”:456}
2019-09-10,{“lng”:12.9,“alt”:413.0,“时间”:“2019-09-10”,“错误”:7.0,“lat”:17.8},南,南
2019-09-10,{“lng”:12.9,“alt”:413.0,“time”:“2019-09-10”,“error”:7.0,“lat”:17.8},{“ack”:123,“bar”:456},{“foo”:123,“bar”:456}
2019-09-10,{“lng”:12.9,“alt”:413.0,“时间”:“2019-09-10”,“错误”:7.0,“lat”:17.8},南,南
2019-09-10,{“lng”:12.9,“alt”:413.0,“time”:“2019-09-10”,“error”:7.0,“lat”:17.8},{“ack”:123,“bar”:456},{“foo”:123,“bar”:456}
2019-09-10,{“lng”:12.9,“alt”:413.0,“时间”:“2019-09-10”,“错误”:7.0,“lat”:17.8},南,南
2019-09-10,{“lng”:12.9,“alt”:413.0,“time”:“2019-09-10”,“error”:7.0,“lat”:17.8},{“ack”:123,“bar”:456},{“foo”:123,“bar”:456}
2019-09-10,{“lng”:12.9,“alt”:413.0,“时间”:“2019-09-10”,“错误”:7.0,“lat”:17.8},南,南
Path.cwd()
- 可以使用
Path('c:/some\u Path\u to\u my\u file')/“file\u name.poo'
- 可以使用
- 是标准库的一部分
重新导入
从pathlib导入路径
p=Path.cwd()/“test.csv”
p2=Path.cwd()/“test2.csv”
p.open('r')作为f:
p2.打开('w')作为f2:
对于cnt,枚举(f)中的行:
如果cnt==0:
行=行。替换(“,”,“|”)
其他:
line=re.sub(r',(?=((?!\})。*\{)[^\{\}]*$)',“|”,line)
f2.写入(行)
新文件:
Time | location | labelA | labelB
2019-09-10{“lng”:12.9,“alt”:413.0,“time”:“2019-09-10”,“error”:7.0,“lat”:17.8}{“ack”:123,“bar”:456}{“foo”:123,“bar”:456}
2019-09-10 |{“lng”:12.9,“alt”:413.0,“时间”:“2019-09-10”,“错误”:7.0,“lat”:17.8}|
2019-09-10{“lng”:12.9,“alt”:413.0,“time”:“2019-09-10”,“error”:7.0,“lat”:17.8}{“ack”:123,“bar”:456}{“foo”:123,“bar”:456}
2019-09-10 |{“lng”:12.9,“alt”:413.0,“时间”:“2019-09-10”,“错误”:7.0,“lat”:17.8}|
2019-09-10{“lng”:12.9,“alt”:413.0,“time”:“2019-09-10”,“error”:7.0,“lat”:17.8}{“ack”:123,“bar”:456}{“foo”:123,“bar”:456}
2019-09-10 |{“lng”:12.9,“alt”:413.0,“时间”:“2019-09-10”,“错误”:7.0,“lat”:17.8}|
2019-09-10{“lng”:12.9,“alt”:413.0,“time”:“2019-09-10”,“error”:7.0,“lat”:17.8}{“ack”:123,“bar”:456}{“foo”:123,“bar”:456}
2019-09-10 |{“lng”:12.9,“alt”:413.0,“时间”:“2019-09-10”,“错误”:7.0,“lat”:17.8}|
解析新文件:
- 现在,这些列将被
正确分隔。请阅读\u csv
- 但是,
、location
和labelA
列是labelB
str
- 用于转换为
dict
对literal\u eval
无效,因此将nan
替换为nan
{}
new_df = df.join(pd.io.json.json_normalize(df["location"])).drop(["location"], axis=1) print(new_df) # Time labelA labelB alt error lat lng time #0 2019-09-10 NaN NaN 413.0 7.0 17.8 12.9 2019-09-10
- 用于转换为