python—通过从dict列中提取一些键/值对,同时将其他键/值对保留为新记录,来反规范化 Dataframe

dbf7pr2w  于 2021-09-08  发布在  Java
关注(0)|答案(1)|浏览(342)

我有一个非常复杂的pandas数据框,它有4列:[id,email id,phone,conversation],但这里的conversation列是一个dict,但存储为字符串,如:

id | email     | phoneNo | conversation
-------------------------------------------------
0  10 | abc@g.com |   123   | {"subject": "abc", "ts": "2021:10:06", "metadata": {"key: value"}, "content": "[email body]", "conversation_id": "100A"
1  12 | xyz@g.com |   789   | {"subject": "xyz", "ts": "2021:10:08", "metadata": {"key: value"}, "to" : "999", "from" : "789", "conversation_id": "101B"

当前数据类型:

id[0] > int
email[0] > str
ph[0] > str
conversation[0] > str

该对话包含客户互动的细节,可以通过短信、电子邮件甚至电话对话进行。
所以,问题是元数据中可能有许多键值对(甚至嵌套列表/dict),这对每个记录都不严格。例如,一种情况中可能有5个这样的键值对(主题、ts、元数据、内容、会话id),而第二种情况中可能有3个(主题、ts、元数据、收件人、发件人、状态、会话id等),以此类推。可以肯定的是,无论是何种通信方式,会话id都将存在,并且每个会话id都是唯一的。
因此,我想以一种方式对这个json进行反规范化,即键值对如下所示:

id | email     | phoneNo | conversation_id |   keys      |   values
------------------------------------------------------------------------
0  10 | abc@g.com |   123   |     100A        |   subject   |    abc
1  10 | abc@g.com |   123   |     100A        |   ts        | 2021:10:06
2  10 | abc@g.com |   123   |     100A        |   metadata  | {"key: value"}
3  10 | abc@g.com |   123   |     100A        |   content   | [email body]
4  12 | xyz@g.com |   789   |     101B        |   subject   |    xyz
5  12 | xyz@g.com |   789   |     101B        |   ts        | 2021:10:08
6  12 | xyz@g.com |   789   |     101B        |   metadata  | {"key: value"}
7  12 | xyz@g.com |   789   |     101B        |   to        |     999
8  12 | xyz@g.com |   789   |     101B        |   from      |     789

预期数据类型:

id[0] > int
email[0] > str
ph[0] > str
conversation_id[0] > str
keys[0] > str
values[0] > str

我正在努力首先将会话列从str转换为dict,然后如何将我需要的会话列保留为单独的列(conversation_id),其余的可以分别放在键/值列中。
我被要求考虑一个可能的函数,它可以接受这个输入 Dataframe 并返回像第二个 Dataframe 那样的值。
我们决定保留键/值对的原因是,将每个键/值对转换为列时存在不确定性,因为它可能是不固定的。这样,我可以将列数固定为6,并在数据库中创建相应的模式以加载它。
但是,如果可以通过输入null来创建“n”个列,而不管另一条记录是否具有该键/值对,这也会很好,但是我不确定以后是否可以将其转换为表模式。
任何帮助都将不胜感激。
谢谢

juzqafwq

juzqafwq1#

你可以用 ast.literal_eval 转换的str表示形式 dict 实际 dict ,然后按以下步骤进行:

from ast import literal_eval

conversations = df.pop('conversation').apply(literal_eval).apply(pd.Series)
df['conversation_id'] = conversations.pop('conversation_id')
stacked_conversation = ( conversations.stack().reset_index(level=1)
                         .set_axis(['keys', 'values'], axis=1) )
result = df.join(stacked_conversation).reset_index(drop=True)

输出:

id      email  phoneNo conversation_id      keys        values
0  10  abc@g.com      123            100A   subject           abc
1  10  abc@g.com      123            100A        ts    2021:10:06
2  10  abc@g.com      123            100A  metadata  {key: value}
3  10  abc@g.com      123            100A   content  [email body]
4  12  xyz@g.com      789            101B   subject           xyz
5  12  xyz@g.com      789            101B        ts    2021:10:08
6  12  xyz@g.com      789            101B  metadata  {key: value}
7  12  xyz@g.com      789            101B        to           999
8  12  xyz@g.com      789            101B      from           789

相关问题