问题:将DataFrame中的一列字典重新转换为一个DataFrame,其中字典key是列名,value是列值。
*思考: 每一行都是一个字典,且在dataframe中是字符串形式,若采用循环遍历的方式将每一行转换为dataframe然后再合并则耗时严重。考虑到字典以及字符串是最接近JSON文件的格式,能否采用一种JSON文件操作方法,快速转换结构形式?
1. JSON存储以及加载中的一些BUG
单引号字符串直接写入JSON是有问题的
obj2 = """
[{'*_6': "F000681Y0022",
'$Num_10': '9',
'$Num_11': '171'
}]"""
with open("test.json","w",encoding="utf-8") as f:
f.write(obj2)
字符串直接写入的正确写法
obj="""[{"姓名": "张三",
"住处": "天朝",
"宠物": "koala",
"兄弟": "李四"
},{"姓名": "李四",
"住处": "天朝",
"宠物": "cat",
"兄弟": "张三"}]"""
with open("test.json","w",encoding="utf-8") as f:
f.write(obj)
若为单引号,如何写入?使用json.dumps()将字典转换为字符串再写入
obj2 = [{'*_6': "F000681Y0022",
'$Num_10': '9',
'$Num_11': '171'
}]
with open("test.json","w",encoding="utf-8") as f:
y = json.dumps(obj2)
f.write(y)
2. 解决今天问题
第一步:将dataframe中该列字符串式的字典转变为列表,1w行耗时0.01s。
第二步:将列表中的字符串式的字典用eval()方法还原为字典格式。1w行耗时0.01s。此时数据形式为一个大列表,列表中包含很多字典。
第三步:将该大列表使用json.dumps()方法转变为一个大的字符串,写入JSON文件中。
第四步:从JSON文件中读出整个内容,有两种方式,第一种为pd.read_json();第二种先读出来,然后使用json.loads()还原为原来的列表格式,再用pd.json_normalize()转变为dataframe格式。1w数据量耗时0.5s。
import json
variable = df['variables'].values.tolist()
var = [eval(var) for var in variable]
with open('test.json', mode='w', encoding='utf-8') as f:
y = json.dumps(var)
f.write(y)
# 方法一
data = open('test.json', encoding='utf-8').read()
data_list = json.loads(data)
da = pd.json_normalize(data_list)
da
# 方法二
import pandas as pd
df = pd.read_json("test.json",encoding="utf-8", orient='records')
df
3. 以上功能集成为函数,独立解决该部分问题
import json
import pandas as pd
import time
def colTodf(df, colName, jsonPath):
# dataframe中一列字典转换为字符串,key是列名
# colName:原dataframe中待转换的列名
# jsonName:存储中间过程json文件路径
start = time.time()
variable = df[colName].values.tolist()
var = [eval(var) for var in variable]
with open(jsonPath, mode='w', encoding='utf-8') as f:
y = json.dumps(var)
f.write(y)
data = pd.read_json(jsonPath, encoding='utf-8', orient='records')
print(time.time() - start)
return data
1w数据量耗时1.1s
能不能不存储到JSON中,直接转换为dataframe文件呢?
import json
import pandas as pd
import time
def colTodf(df, colName, jsonPath):
# dataframe中一列字典转换为字符串,key是列名
start = time.time()
variable = df[colName].values.tolist()
var = [eval(var) for var in variable]
data = pd.json_normalize(var)
data['stage'] = df['INDEX'].values
print(time.time() - start)
return data
这样耗时更短