长度不规则的列表中的MultiIndex

时间:2019-11-19 17:48:17

标签: python pandas multi-index

我有一个列表列表,希望将其制作成多索引熊猫数据框,然后将其合并到原始熊猫数据框。列表的每一行包含一个观察值,列表中的值包含与该观察值匹配的相应行。

这是我所拥有的简单版本:

原始数据框的格式如下:

original=(pd.DataFrame([['JFK','New York, NY'],['EWR','Newark, NJ'],
                        ['BWI','Baltimore, MD'],['PHL','Philadelphia, PA'],
                        ['DCA','Washington, DC']],columns=['ID','City']))
original
    ID              City
0  JFK      New York, NY
1  EWR        Newark, NJ
2  BWI     Baltimore, MD
3  PHL  Philadelphia, PA
4  DCA    Washington, DC

匹配的输出(将位置与特定半径内的其他位置匹配)是一个列表列表,如下所示:

matches=[[0],[1,3],[2],[1,3],[4]]
matches
[[0], [1, 3], [2], [1, 3], [4]]

这就是我想要的样子:

              ID              City
Org Match
0   0        JFK      New York, NY
1   1        EWR        Newark, NJ 
    3        PHL  Philadelphia, PA 
2   2        BWI     Baltimore, MD
3   1        EWR        Newark, NJ
    3        PHL  Philadelphia, PA
4   4        DCA    Washington, DC

我知道如何加入多索引级别,但是无法弄清楚如何正确地使用多索引。最终,这将需要大规模进行。也乐于以不同的方式对待。

潜在的问题是将位置与给定距离内的所有其他位置进行匹配。这是在单独的模块中完成的,输出是上面引用的列表的列表。

3 个答案:

答案 0 :(得分:1)

我将构建索引,并与originalset_index合并:

ret = (pd.concat(pd.DataFrame({'Org':i, 'Match':v}) for i,v in enumerate(matches))
         .merge(original, left_on='Match', right_index=True, how='left')
         .set_index(['Org','Match'])
      )

输出:

            ID              City
Org Match                       
0   0      JFK      New York, NY
1   1      EWR        Newark, NJ
    3      PHL  Philadelphia, PA
2   2      BWI     Baltimore, MD
3   1      EWR        Newark, NJ
    3      PHL  Philadelphia, PA
4   4      DCA    Washington, DC

答案 1 :(得分:1)

您可以使用concat

matches = [[0], [1, 3], [2], [1, 3], [4]]

result = pd.concat([df.iloc[match] for match in matches], keys=list(range(len(matches))), names=['Org', 'Match'])

print(result)

输出

            ID              City
Org Match                       
0   0      JFK      New York, NY
1   1      EWR        Newark, NJ
    3      PHL  Philadelphia, PA
2   2      BWI     Baltimore, MD
3   1      EWR        Newark, NJ
    3      PHL  Philadelphia, PA
4   4      DCA    Washington, DC

答案 2 :(得分:1)

matches构造一个序列,并使用explode获取要用于reindexset_index的值。最后,swaplevel

s = pd.Series(matches).explode()
df = original.reindex(s).set_index(s.index, append=True).swaplevel(1,0)

Out[54]:
      ID              City
0 0  JFK      New York, NY
1 1  EWR        Newark, NJ
  3  PHL  Philadelphia, PA
2 2  BWI     Baltimore, MD
3 1  EWR        Newark, NJ
  3  PHL  Philadelphia, PA
4 4  DCA    Washington, DC

或者您可以构造多重索引并将其用于reindexset_index并重新排序最终df的多重索引的顺序

ix = pd.MultiIndex.from_tuples([(i, y) for i, x in enumerate(matches) for y in x])
df = original.reindex(ix.get_level_values(1)).set_index(ix.get_level_values(0), append=True).swaplevel(1,0) 

Out[43]:
      ID              City
0 0  JFK      New York, NY
1 1  EWR        Newark, NJ
  3  PHL  Philadelphia, PA
2 2  BWI     Baltimore, MD
3 1  EWR        Newark, NJ
  3  PHL  Philadelphia, PA
4 4  DCA    Washington, DC