Python 在pandas中解析字符串化词典的列
我有这个数据框:Python 在pandas中解析字符串化词典的列,python,pandas,Python,Pandas,我有这个数据框: df = pd.DataFrame([ { "name": "foo", "results": "{'lower_bound': '15000', 'upper_bound': '19999'}"}, { "name": "bar", "results": "{'lower_bound': '10000', 'upper_bound': '14999'}"} ]) 现在看起来是这样的: name results 0 foo {'lower_b
df = pd.DataFrame([
{ "name": "foo", "results": "{'lower_bound': '15000', 'upper_bound': '19999'}"},
{ "name": "bar", "results": "{'lower_bound': '10000', 'upper_bound': '14999'}"}
])
现在看起来是这样的:
name results
0 foo {'lower_bound': '15000', 'upper_bound': '19999'}
1 bar {'lower_bound': '10000', 'upper_bound': '14999'}
我想将结果
列转换为结构化数据,以便可以筛选df.lower_bound小于13000的行
我如何才能做到这一点?这可能不是最佳或最好的方法:
from ast import literal_eval
df['results'] = df['results'].apply(lambda i: literal_eval(i))
这会将“结果”
列中的字符串格式的值转换为字典。输出:
name results
0 foo {'lower_bound': '15000', 'upper_bound': '19999'}
1 bar {'lower_bound': '10000', 'upper_bound': '14999'}
然后:
df['results'] = df['results'].apply(lambda i: {k:int(v) for k,v in i.items()})
这将该列中字典的值从字符串转换为整数格式。输出:
name results
0 foo {'lower_bound': 15000, 'upper_bound': 19999}
1 bar {'lower_bound': 10000, 'upper_bound': 14999}
现在,获取字典的下限
键的值小于13000的行,即使任何行中没有下限
键,也要处理该情况:
df.loc[map(lambda i:i.get('lower_bound', '0')<13000, df['results'])]
如果您不想修改现有的数据帧,可以通过将“结果”转换为数据帧,然后过滤来生成条件:
mask = (pd.DataFrame(df['results'].apply(ast.literal_eval).tolist())
.astype(int)
.eval('lower_bound < 13000'))
df[mask]
name results
1 bar {'lower_bound': '10000', 'upper_bound': '14999'}
另一种方法是使用json_normalize和ast_literal
from pandas.io.json import json_normalize
from ast import literal_eval
然后拆分JSON列,然后将它们合并回索引中
s = json_normalize(df['results'].apply(literal_eval).astype(int))
df_new = pd.merge(df,s,right_index=True,left_index=True)
print(df_new)
name Results lower_bound upper_bound
0 foo {'lower_bound': '15000', 'upper_bound': '19999'} 15000 19999
1 bar {'lower_bound': '10000', 'upper_bound': '14999'} 10000 14999
对于数据类型:
print(df_new.dtypes)
name object
results object
lower_bound int32
upper_bound int32
dtype: object
您可以将字符串表达式转换为JSON兼容格式,方法是将单引号替换为双引号,然后从JSON转换为dict:
df = pd.DataFrame([
{ "name": "foo", "results": "{'lower_bound': '15000', 'upper_bound': '19999'}"},
{ "name": "bar", "results": "{'lower_bound': '10000', 'upper_bound': '14999'}"}
])
pd.concat([df, pd.DataFrame(df.pop('results').apply(lambda x: json.loads(x.replace("'", '"'))).tolist())], axis=1)
这比使用ast.literal\u eval更有效,如果您有许多行,您将清楚地看到执行时间的差异。您可以尝试:
df = pd.DataFrame([
{ "name": "foo", "results": "{'lower_bound': '15000', 'upper_bound': '19999'}"},
{ "name": "bar", "results": "{'lower_bound': '10000', 'upper_bound': '14999'}"}
])
lower_bound = []
upper_bound = []
for index, row in df.iterrows():
r = eval(row['results'])
lower_bound.append(r['lower_bound'])
upper_bound.append(r['upper_bound'])
df['lower_bound'] = lower_bound
df['upper_bound'] = upper_bound
print(df[['name', 'lower_bound', 'upper_bound']])
结果:
name lower_bound upper_bound
0 foo 15000 19999
1 bar 10000 14999
未经测试,但我认为您可以使用from
pandas.io.json import json\u normalize
然后调用列上的函数,explode是另一个可以查看的函数,谢谢。第一步可能是从字符串字段转换它们?你说得对,谢谢!你不经意间教会了我一些新东西。
df = pd.DataFrame([
{ "name": "foo", "results": "{'lower_bound': '15000', 'upper_bound': '19999'}"},
{ "name": "bar", "results": "{'lower_bound': '10000', 'upper_bound': '14999'}"}
])
lower_bound = []
upper_bound = []
for index, row in df.iterrows():
r = eval(row['results'])
lower_bound.append(r['lower_bound'])
upper_bound.append(r['upper_bound'])
df['lower_bound'] = lower_bound
df['upper_bound'] = upper_bound
print(df[['name', 'lower_bound', 'upper_bound']])
name lower_bound upper_bound
0 foo 15000 19999
1 bar 10000 14999