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