【问题标题】:Split key value string in python and move it in a df column在python中拆分键值字符串并将其移动到df列中
【发布时间】:2019-08-04 23:08:25
【问题描述】:

这是我拥有的列,我想拆分为键值并存储在 pandas df 的新列中。

{"FontStyle"=>"Gill Sans Standard", "FontSize"=>"Medium (3mm)"}
{"Font Style"=>"Gill Sans Standard","Font Size"=>"Medium (3mm)"}
{"Font Style":"Script","Font Size":"Medium (3mm)"}
{"Font Style"=>"Gill Sans Standard","Font Size"=>"Medium (3mm)"}
{"Font Style":"Gill Sans Standard","Font Size":"Medium (3mm)"}

主要问题是其中一些有 '=>' 而另一些有冒号

我想要 df 中的两个新列,一个用于字体样式,另一个用于字体大小以及其中的尊重值

如果有人可以帮助我实现这一点,那就太好了,而且如果您可以向我推荐一些关于正则表达式的书籍/教程,那就太好了。

谢谢

【问题讨论】:

  • 你需要的输出是什么,能不能也提一下?

标签: python regex pandas split


【解决方案1】:

到目前为止,这不是最有效的代码,但它可以完成工作。

import pandas as pd
import ast

text = '''{"FontStyle"=>"Gill Sans Standard", "FontSize"=>"Medium (3mm)"}
{"Font Style"=>"Gill Sans Standard","Font Size"=>"Medium (3mm)"}
{"Font Style"=>"Script","Font Size"=>"Medium (3mm)"}
{"Font Style"=>"Gill Sans Standard","Font Size"=>"Medium (3mm)"}'''

my_list = []

text = text.replace("FontStyle", "Font Style")
text = text.replace("FontSize", "Font Size")
text = text.replace("=>", ":")
text = text.split("\n")

for one_dict in text:
    my_list.append(ast.literal_eval(one_dict))

df = pd.DataFrame(my_list)
print(df)

以上代码的输出:

      Font Size          Font Style
0  Medium (3mm)  Gill Sans Standard
1  Medium (3mm)  Gill Sans Standard
2  Medium (3mm)              Script
3  Medium (3mm)  Gill Sans Standard

我希望这会有所帮助。 :-) 如果有,请告诉我。

【讨论】:

    【解决方案2】:

    试试这个:

    import ast
    df['col'] = df['col'].str.replace('=>', ': ').str.replace('FontSize', 'Font Size').str.replace('FontStyle', 'Font Style')
    df['col']= df["col"].apply(lambda x : dict(ast.literal_eval(x)))
    df1 = df['col'].apply(pd.Series)
    

    【讨论】:

    • 你能告诉我为什么不使用 eval 吗?
    【解决方案3】:

    我觉得regex这里没必要,用:

    import ast
    
    print (df)
                                                     col
    0  {"FontStyle"=>"Gill Sans Standard", "FontSize"...
    1  {"Font Style"=>"Gill Sans Standard","Font Size...
    2  {"Font Style":"Script","Font Size":"Medium (3m...
    3  {"Font Style"=>"Gill Sans Standard","Font Size...
    4  {"Font Style":"Gill Sans Standard","Font Size"...
    5                                                NaN
    

    d = {'=>':':', 'FontSize':'Font Size','FontStyle':'Font Style'}
    
    regex = '|'.join(r"{}".format(x) for x in d.keys())
    df1 = (df['col'].dropna()
                    .str.replace(regex, lambda x: d[x.group()], regex=True)
                    .apply(ast.literal_eval))
    df2 = pd.DataFrame(df1.values.tolist())[['Font Size','Font Style']].dropna(how='all')
    print (df2)
          Font Size          Font Style
    0  Medium (3mm)  Gill Sans Standard
    1  Medium (3mm)  Gill Sans Standard
    2  Medium (3mm)              Script
    3  Medium (3mm)  Gill Sans Standard
    4  Medium (3mm)  Gill Sans Standard
    

    解释

    1. 首先删除DataFrame.dropna 的缺失行
    2. 然后对字典中的值使用Series.str.replace
    3. 通过ast.literal_eval将值转换为字典
    4. 创建新数据帧
    5. 如有必要,仅按列表过滤列并仅移动 NaNs 行

    【讨论】:

    • 我收到此错误消息 ` malformed node or string: nan `
    • 该列有 145 个空值
    • 解决方案工作正常,有没有办法将这些列合并为 2?是的,我们需要删除 nan 值
    • @Vijayaraghavan - 只是看到有必要的多次替换,所以编辑了答案。
    猜你喜欢
    • 2021-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-23
    • 1970-01-01
    • 1970-01-01
    • 2011-11-29
    相关资源
    最近更新 更多