将元组的无序列表转换为 pandas DataFrame

Posted

技术标签:

【中文标题】将元组的无序列表转换为 pandas DataFrame【英文标题】:Converting unordered list of tuples to pandas DataFrame 【发布时间】:2018-05-29 20:57:57 【问题描述】:

我正在使用库 usaddress 从我拥有的一组文件中解析地址。我希望我的最终输出是一个数据框,其中列名代表地址的一部分(例如街道、城市、州),行代表我提取的每个单独的地址。例如:

假设我有一个地址列表:

addr = ['123 Pennsylvania Ave NW Washington DC 20008', 
        '652 Polk St San Francisco, CA 94102', 
        '3711 Travis St #800 Houston, TX 77002']

然后我使用 usaddress 提取它们

info = [usaddress.parse(loc) for loc in addr]

“info”是一个元组列表,如下所示:

[[('123', 'AddressNumber'),
  ('Pennsylvania', 'StreetName'),
  ('Ave', 'StreetNamePostType'),
  ('NW', 'StreetNamePostDirectional'),
  ('Washington', 'PlaceName'),
  ('DC', 'StateName'),
  ('20008', 'ZipCode')],
 [('652', 'AddressNumber'),
  ('Polk', 'StreetName'),
  ('St', 'StreetNamePostType'),
  ('San', 'PlaceName'),
  ('Francisco,', 'PlaceName'),
  ('CA', 'StateName'),
  ('94102', 'ZipCode')],
 [('3711', 'AddressNumber'),
  ('Travis', 'StreetName'),
  ('St', 'StreetNamePostType'),
  ('#', 'OccupancyIdentifier'),
  ('800', 'OccupancyIdentifier'),
  ('Houston,', 'PlaceName'),

我希望每个列表(对象“info”中有 3 个列表)代表一行,每个元组对的 2 值表示一列,元组对的 1 值是值。注意:内部列表的链接并不总是相同的,因为不是每个地址都会包含所有信息。

任何帮助将不胜感激!

谢谢

【问题讨论】:

不同之处在于元组列表是无序的,或者说是稀疏的。 OccupancyIdentifier 只出现在第三项中,而且出现了两次,所以这不是一个简单的 (value,key) 列表,我们必须连接多个相邻的子值 【参考方案1】:

不确定是否有一个 DataFrame 构造函数可以完全按照您现在的方式处理 info。 (可能是from_records 或者from_items?--还是觉得这个结构不能直接兼容。)

这里有一些操作可以得到你正在寻找的东西:

cols = [j for _, j in info[0]]

# Could use nested list comprehension here, but this is probably
#     more readable.
info2 = []
for row in info:
    info2.append([i for i, _ in row])

pd.DataFrame(info2, columns=cols)

  AddressNumber    StreetName StreetNamePostType StreetNamePostDirectional   PlaceName StateName ZipCode
0           123  Pennsylvania                Ave                   NW       Washington        DC   20008
1           652          Polk                 St                  San       Francisco,        CA   94102

【讨论】:

【参考方案2】:

感谢您的回复!我最终做了一个完全不同的解决方法,如下所示:

我检查了文档以查看来自usaddress 的所有可能的 parse_tags,创建了一个 DataFrame,其中所有可能的标签作为列,另一列包含提取的地址。然后我继续使用regex 从列中解析和提取信息。代码如下!

parse_tags = ['Recipient','AddressNumber','AddressNumberPrefix','AddressNumberSuffix',
'StreetName','StreetNamePreDirectional','StreetNamePreModifier','StreetNamePreType',
'StreetNamePostDirectional','StreetNamePostModifier','StreetNamePostType','CornerOf',
'IntersectionSeparator','LandmarkName','USPSBoxGroupID','USPSBoxGroupType','USPSBoxID',
'USPSBoxType','BuildingName','OccupancyType','OccupancyIdentifier','SubaddressIdentifier',
'SubaddressType','PlaceName','StateName','ZipCode']

addr = ['123 Pennsylvania Ave NW Washington DC 20008', 
        '652 Polk St San Francisco, CA 94102', 
        '3711 Travis St #800 Houston, TX 77002']

df = pd.DataFrame('Addresses': addr)
pd.concat([df, pd.DataFrame(columns = parse_tags)])

然后我创建了一个新列,从 usaddress 解析列表中生成一个字符串并将其命名为“Info”

df['Info'] = df['Addresses'].apply(lambda x: str(usaddress.parse(x)))

现在这是主要的解决方法。我遍历每个列名并在相应的“信息”单元格中查找它,并应用正则表达式来提取它们存在的信息!

for colname in parse_tags:
    df[colname] = df['Info'].apply(lambda x: re.findall("\('(\S+)', ''\)".format(colname), x)[0] if re.search(
    colname, x) else "")

这可能不是最有效的方法,但它对我的目的有效。感谢大家提供建议!

【讨论】:

以上是关于将元组的无序列表转换为 pandas DataFrame的主要内容,如果未能解决你的问题,请参考以下文章

将元组列表转换为 Pandas 系列

将元组的字符串表示形式转换为真正的元组

Spark 2.0:如何将元组的 RDD 转换为 DF [重复]

如何将元组转换为命名元组?

如何创建将二叉树转换为元组的函数?

list使用