【问题标题】:Parsing key-value pairs into DataFrame columns将键值对解析为 DataFrame 列
【发布时间】:2014-11-23 23:05:33
【问题描述】:

我在 pandas Series 中有按行嵌套的键值对。将它们分成单独的列的最有效/优化的方法是什么? (我可以解压缩并进行转换,但是最好的方法是什么?)

知道:

  • 事先输入键名
  • 每条记录中的键数
  • 每条记录中键的顺序

这些行是 unicode 字符串的列表。提取后,值将始终为 bigint。

输入:

parsedSeries.head()

0 [key1=774, key2=238]
1 [key1=524, key2=101, key3=848]
2 [key3=843]
3 [key1=232, key3=298, key2=457]

预期输出:

record   key1   key2   key3
0        774    238    NAN
1        524    101    848
2        NAN    NAN    843
3        232    457    298

请注意,输入由包含格式为 u"X=Y" 的 Unicode 字符串的列表组成,其中 X 被假定为遵守在 Python 中用作属性名称所需的任何约定,并且 Y 始终可以被解释作为整数。例如,可以使用以下内容来构造上面的示例数据:

pandas.Series([[u"key1=774", u"key2=238"],
               [u"key1=524", u"key2=101", u"key3=848"],
               [u"key3=843"],
               [u"key1=232", u"key3=298", u"key2=457"]])

【问题讨论】:

  • parsedSeries.ix[0] 的类型是什么。您的示例显示了 [key1=774, key2=238],但这是什么?不能是列表,是dict吗?您是否有一个系列,其中每个条目都是dict?还是它被组织成一个 2 元组的序列,还是什么?
  • 这是一个列表... In [81]: type(parsedSeries.ix[0]) Out[81]: list.我将 str.split 应用于 df 以创建该列表
  • 好的,那么type(parsedSeries.ix[0][0])是什么?
  • 它是 Unicode。谢谢!
  • 所以它是一个 Unicode 字符串列表,因此每个字符串的格式为 u"X=Y",其中 X 将被解释为列名,Y 作为当前列的值排?那是对的吗? Y 是否有固定的数据类型?你还能保证X 遵守正确的 Python 属性命名约定吗? (例如,它不是一个带有点(.)的字符串......)

标签: python performance parsing pandas


【解决方案1】:

“最佳”解决方案可能首先是不要让自己陷入这种情况。大多数情况下,当您在 Series 或 DataFrame 中有非标量数量时,您已经朝着错误的方向迈出了一步,因为您无法真正应用向量操作。

无论如何,从您的系列开始,您可以执行以下操作:

>>> ds = [dict(w.split('=', 1) for w in x) for x in s]
>>> pd.DataFrame.from_records(ds)
  key1 key2 key3
0  774  238  NaN
1  524  101  848
2  NaN  NaN  843
3  232  457  298

【讨论】:

    【解决方案2】:

    为了将值处理为整数而不是字符串,对 DSM 使用 from_records 进行了非常细微的调整。

    def key_to_int(split_vals):
        return (split_vals[0], int(split_vals[1]))
    
    def dictify(row):
        return dict(key_to_int(elem.split("=")) for elem in row)
    
    pandas.DataFrame.from_records(parsedSeries.map(dictify))
    

    给予

    Out[518]: 
       key1  key2  key3
    0   774   238   NaN
    1   524   101   848
    2   NaN   NaN   843
    3   232   457   298
    
    [4 rows x 3 columns]
    

    其中值是整数(由于 NaN 值和 NumPy 仍然不支持整数 NaN 值,列仍然是 float 类型)。

    【讨论】:

      【解决方案3】:

      好的,根据您的示例的精确程度,您的最终答案可能会有所不同。具体来说,可能会调整解析数据的正则表达式。

      让我们做一些 imoprts 并设置你的数据文件:

      import re
      import pandas as pd
      from StringIO import StringIO
      
      f = StringIO("""0 [key1=774, key2=238]
      1 [key1=524, key2=101, key3=848]
      2 [key3=843]
      3 [key1=232, key3=298, key2=457]""")
      

      现在我们可以开始了。首先只是一些正则表达式的魔法来获得你的行的字典表示:

      # get the dicts
      rows = [dict(re.findall('(key[0-9]*)=([0-9]*)',l)) for l in f]
      # convert values to ints
      rows = [dict((k,int(v)) for k,v in row.items()) for row in rows]
      rows
      

      输出:

      [{'key1': 774, 'key2': 238},
       {'key1': 524, 'key2': 101, 'key3': 848},
       {'key3': 843},
       {'key1': 232, 'key2': 457, 'key3': 298}]
      

      这只是正则表达式,但你就在那里:

      pd.DataFrame(rows)
      

      输出:

        key1 key2 key3
      0  774  238  NaN
      1  524  101  848
      2  NaN  NaN  843
      3  232  457  298
      

      如果您愿意,可以转换为单行,但我将其分为两步,以便您可以调整正则表达式以适合您的实际数据文件。

      【讨论】:

        猜你喜欢
        • 2023-03-15
        • 2013-02-11
        • 1970-01-01
        • 2018-08-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多