【问题标题】:How to iterate through DataFrame rows and grab values from dicts in cols?如何遍历 DataFrame 行并从 cols 中的 dicts 中获取值?
【发布时间】:2018-11-15 06:43:25
【问题描述】:

Features_Frame

每个特征框都是一批数据。我想提取 col 几何中关键“坐标”的所有值,并迭代地插入到另一个 df 中。

使用相同的 df,我还想存储从属性 col 提取的数据。属性 col 有很多键。

每个源框架都将包含 'geometry':'coordinates' 和 'properties',它们由各种键组成。

这个新 DataFrame 中的每个 col 都将是“几何”或“属性”中的一个键。

例如:

      coordinates          name
0      [-108.600,39.09]    'Target'
1      [51.459,82.04]      'Costco'
2      [-35.459,82.04]     'BJ's Wholesale Club'
3      [98.459,12.07]      'Walgreens'
4      [105.404,96.04]     'Walmart

我可以通过以下方式访问这两个列:

coord_frame = features_frame['geometry'][:]
properties_frame = features_frame['properties'][:]

但这只会将框架一分为二。通常,如果我这样做了:

Feature_Frame['geometry'][:]['coordinates']

如果我这样做了,我会在几何 col 中为所有行获取坐标键的值:

Feature_Frame['properties'][:]['name']

我会在所有行的属性 col 中获取 name 键的值。

相反,我只是收到一个关键错误,提示名称或坐标不存在。

【问题讨论】:

  • 提供答案而不是将图像转换为文本数据会很容易。请将您的数据框粘贴为可编辑的文本数据。

标签: python pandas dictionary dataframe


【解决方案1】:

将字典列表提供给pd.DataFrame 构造函数

pd.Series.apply 是一个 Python 级别的循环,除了它通常执行一个简单的列表解析。一个更好的主意是使用pd.DataFrame 构造函数中使用的优化代码。这是一个例子:

df = pd.DataFrame({'geometry': [{'coordinates': [-108.600,39.09], 'name': 'Target'},
                                {'coordinates': [51.459,82.04], 'name': 'Costco'}]})

print(df)

                                            geometry
0  {'coordinates': [-108.6, 39.09], 'name': 'Targ...
1  {'coordinates': [51.459, 82.04], 'name': 'Cost...

res = pd.DataFrame(df['geometry'].values.tolist())

print(res)

       coordinates    name
0  [-108.6, 39.09]  Target
1  [51.459, 82.04]  Costco

对多个系列的字典使用concat

以上可以扩展到任意系列的字典:

df = pd.DataFrame({'geometry': [{'coordinates': [-108.600,39.09], 'name': 'Target'},
                                {'coordinates': [51.459,82.04], 'name': 'Costco'}],
                   'properties': [{'osm_id': 288700723, 'osm_tye': 'W'},
                                  {'osm_id': 52734154, 'osm_tye': 'W'}]})

res = pd.concat((pd.DataFrame(df[col].values.tolist()) for col in df), axis=1)

print(res)

       coordinates    name     osm_id osm_tye
0  [-108.6, 39.09]  Target  288700723       W
1  [51.459, 82.04]  Costco   52734154       W

【讨论】:

    【解决方案2】:

    怎么样

    df_new = pd.DataFrame()
    

    然后例如

    df_new['coordinates'] = features_frame['geometry'].apply(lambda x: x['coordinates'])
    

    df_new['name'] = features_frame['properties'].apply(lambda x: x['name'])
    

    如果你想对所有键都这样做,你可以循环遍历第一行中示例性 dict 的键:

    for key in features_frame.geometry[0]:
        df_new[key] = features_frame.geometry.apply(lambda x: x[key])
    
    for key in features_frame.properties[0]:
        df_new[key] = features_frame.properties.apply(lambda x: x[key])
    

    补充:
    ...如果geometry- 和properties-dicts 中有相同的键,您可以在创建新列时轻松装饰它们以防止覆盖:

    for ...
        df_new['geom_' + key] = ...
    for ...
        df_new['prop_' + key] = ...
    

    编辑:

    如果列中的某些字典没有所有键,则使用默认值,例如None 应该被退回。
    为此,只需在 lambda 函数中使用get-方法,它允许定义默认值,而不是索引:

    lambda x: x.get(key, None)
    

    这至少是针对关键错误的适当解决方案。
    但是,如果代码没有遍历所有键,因为第一行中的字典不能代表所有字典,则首先必须创建所有键的列表。
    进入这个列表有不同的可能性:

    1. 理想情况下,您已经知道其他地方的所有密钥。然后你可以把它们放在一个列表中并迭代它而不是第一个字典。

    2. 也许您知道至少有一个具有最多键的字典,并且这个最长的字典具有所有键,并且同一列中较短字典的键始终是子集。然后你可以找到

      longest_dict = sorted(df.geometry, key=len)[-1]
      
    3. 也许你对钥匙一无所知。因此,您必须收集出现在列中任何位置的所有不同键:

      all_keys = []
      for d in df.geometry:
          all_keys.extend(d)
      all_keys = set(all_keys)
      

    【讨论】:

    • 太完美了,谢谢。但是如何将该 lambda 应用到 f​​eatures_frame.properties 中的所有行?
    • 我不太明白您的问题 - 您是否尝试过代码并且 df_new 中缺少行?通常apply 适用于数据帧的所有行。
    • 例如,并非所有行都有键“housenumber”。如果我执行上述操作,那么我会得到一个 KeyError: 'housenumber',我已经尝试过/除了,但是所有其他行的 'housenumber' 数据都被删除了。所以我想我的问题是......我如何解释第一行并不总是与其他行具有相同的键?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-25
    • 2022-10-25
    • 2022-11-01
    • 2012-05-30
    相关资源
    最近更新 更多