从pandas中的JSON列中提取属于特定键的值

2024-06-28 20:44:27 发布

您现在位置:Python中文网/ 问答频道 /正文

例如,我有一个如下所示的数据帧:

    name      eventlist
0   a         [{'t': '1234', 'n': 'user_engagem1'},{'t': '2345', 'n': 'user_engagem2'},{'t': '3456', 'n': 'user_engagem3'}]
1   b         [{'t': '2345', 'n': 'user_engagem4'},{'t': '1345', 'n': 'user_engagem5'},{'t': '1356', 'n': 'user_engagem6'},{'t': '1345', 'n': 'user_engagem5'},{'t': '1359', 'n': 'user_engagem6'}]
2   c         [{'t': '1334', 'n': 'user_engagem3'},{'t': '2345', 'n': 'user_engagem4'},{'t': '3556', 'n': 'user_engagem2'}]

我和他一起闲逛关于芬德尔用一个字符串,它似乎有效,我得到的结果是 ['1234'、'2345'、'3456'],但我无法将其应用到dataframe中

^{pr2}$

我想得到的结果是

    name      eventlist

0   a         ['1234', '2345', '3456']
1   b         ['2345', '1345','1234','1356', '1356']
2   c         ['1334', '2345', '3556']

或者更好,我可以得到这样的结果

    name      t_first       t_last
0   a         1234           3456
1   b         2345           1359
2   c         1334           3556

Tags: 数据字符串namedataframefirstlastuserpr2
3条回答
df['eventlist'] = df['eventlist'].map(lambda x:[i['t'] for i in x])
df
     name                       eventlist
   0    a              [1234, 2345, 3456]
   1    b  [2345, 1345, 1356, 1345, 1359]
   2    c              [1334, 2345, 3556]

df['t_first'] = df['eventlist'][0]
df['t_last']=df['eventlist'].map(lambda x:x[len(x)-1])
df = df[['name','t_first','t_last']]
df
     name t_first t_last
   0    a    1234   3456
   1    b    2345   1359
   2    c    3456   3556

您可以使用字符串来转换字典列表中的ast.literal_eval,然后通过t和{}s获得值:

import ast

out = []
for x in df.pop('eventlist'):
    a = ast.literal_eval(x)
    out.append([a[0].get('t'), a[-1].get('t')])

或使用re.findall

^{pr2}$
print (out)
[['1234', '3456'], ['2345', '1359'], ['1334', '3556']]

然后将DataFrame和{}创建为原始:

df = df.join(pd.DataFrame(out, columns=['t_first','t_last'], index=df.index))
print (df)
  name t_first t_last
0    a    1234   3456
1    b    2345   1359
2    c    1334   3556

另一个带有^{}^{}新列的解决方案:

a = df.pop('eventlist').str.findall(r"t': '(.+?)'")
df = df.assign(t_first= a.str[0], t_last = a.str[-1])

str.findall需要一个参数:regex模式。在

# Call `pop` here to remove the "events" column.
v = df.pop('eventlist').str.findall(r"t': '(.+?)'")
print(v)

0                [1234, 2345, 3456]
1    [2345, 1345, 1356, 1345, 1359]
2                [1334, 2345, 3556]
Name: events, dtype: object

然后可以将其加载到单独的列中:

^{pr2}$

另一个更好的选择是使用re.compile预编译模式并在循环中运行,从findall结果中提取第一个和最后一个项目。在

import re

p = re.compile(r"t': '(.+?)'")
out = []
for name, string in zip(df.name, df.pop('eventlist')):
    a = p.findall(string)
    out.append([name, a[0], a[-1]])

pd.DataFrame(out, columns=['name', 't_first','t_last'], index=df.index)

  name t_first t_last
0    a    1234   3456
1    b    2345   1359
2    c    1334   3556

如果需要将它们转换为int,请将out.append([name, a[0], a[-1]])替换为out.append([name, int(a[0]), int(a[-1])])。在


上面的解决方案假设您总是有多个匹配项。如果可能只有一个匹配项或没有匹配项,则可以通过检查count后面的匹配数来修改解决方案。在

p = re.compile(r"t': '(.+?)'")
out = []
for name, string in zip(df.name, df.pop('eventlist')):
    first = second = np.nan
    if pd.notna(string):
        a = p.findall(string)
        if len(a) > 0:
            first = int(a[0])
            second = int(a[-1]) if len(a) > 1 else second

    out.append([name, first, second])

pd.DataFrame(out, columns=['name', 't_first','t_last'], index=df.index)

  name  t_first  t_last
0    a     1234    3456
1    b     2345    1359
2    c     1334    3556

相关问题 更多 >