pandas 将阵列数据与子阵列数据匹配

hvvq6cgz  于 2023-06-20  发布在  其他
关注(0)|答案(2)|浏览(106)

我有一个子数组 itemdata,长度为6行。此数据最初在主数组中找到,但已重新格式化,因此每行有1个唯一产品。
我有一个主数组 saledata,长度为4行,看起来有点像这样:

id    sub-array
        0   001   [{'type': 'line_items', 'id': '78', 'attributes': {'status': 'allocated', 'quantity': 1, 'various_other_data': 'etc'}}]
        1   002   [{'type': 'line_items', 'id': '80', 'attributes': {'status': 'allocated', 'quantity': 2, 'various_other_data': 'etc'}}]
        2   003   [{'type': 'line_items', 'id': '85', 'attributes': {'status': 'allocated', 'quantity': 1, 'various_other_data': 'etc'}}, {'type': 'line_items', 'id': '86', 'attributes': {'status': 'allocated', 'quantity': 1, 'various_other_data': 'etc'}}]
        3   004   [{'type': 'line_items', 'id': '92', 'attributes': {'status': 'allocated', 'quantity': 2, 'various_other_data': 'etc'}}, {'type': 'line_items', 'id': '93', 'attributes': {'status': 'allocated', 'quantity': 2, 'various_other_data': 'etc'}}]

然后我得到了sub-array itemdata(基本上就是json归一化的column sub-array):

type        id   attributes.status   attributes.quantity    attributes.various_other_data
0   line_item   78   allocated           1                      etc
0   line_item   80   allocated           2                      etc
0   line_item   85   allocated           1                      etc
1   line_item   86   allocated           1                      etc
0   line_item   92   allocated           2                      etc
1   line_item   93   allocated           2                      etc

目前,我将子数组视为字符串(在它被第二个dataframe规范化之后),这允许我执行以下操作:

for f in itemdata['id']:
    df['sub-array'].str.contains(f)

其产生以下:

0     True
1    False
2    False
3    False
Name: relationships.line_items.data, dtype: bool
0    False
1     True
2    False
3    False
Name: relationships.line_items.data, dtype: bool
0    False
1    False
2     True
3    False
Name: relationships.line_items.data, dtype: bool
0    False
1    False
2     True
3    False
Name: relationships.line_items.data, dtype: bool
0    False
1    False
2    False
3     True
Name: relationships.line_items.data, dtype: bool
0    False
1    False
2    False
3     True
Name: relationships.line_items.data, dtype: bool

这是正确的!但是现在我试图将子数组与父数组进行匹配,将上述结果的索引与初始数组 saledata 进行匹配,其中True但正在努力找到正确的方法来做到这一点。
Python似乎不喜欢下面的方法(Series的真值是模糊的yada yada yada),并且不确定如何继续。

for f in itemdata['id']:
    if df['sub-array'].str.contains(f) == True:

任何建议都非常感谢!
编辑:
这就是我要找的(注意etc是关闭的&不确定pandas是否允许多行具有相同的索引值-如果不是,这不是一个大问题):

id   type         itemdata.id   itemdata.attributes.status   itemdata.attributes.quantity
    0   001   line_items   78            allocated              etc
    1   002   line_items   80            allocated              etc
    2   003   line_items   85            allocated              etc
    2   003   line_items   86            allocated              etc
    3   004   line_items   92            allocated              etc
    3   004   line_items   93            allocated              etc
ccrfmcuu

ccrfmcuu1#

如果需要在规范化sub-array后追加id(或多列),可以使用DataFrame.join,并通过Series.explode分解行设置索引:

import ast

df['sub-array'] = df['sub-array'].apply(ast.literal_eval)

s = df['sub-array'].explode()

cols = ['id']
df = df[cols].add_suffix('_parent').join(pd.json_normalize(s).set_index(s.index))
print (df)
  id_parent        type  id attributes.status  attributes.quantity  \
0       001  line_items  78         allocated                    1   
1       002  line_items  80         allocated                    2   
2       003  line_items  85         allocated                    1   
2       003  line_items  86         allocated                    1   
3       004  line_items  92         allocated                    2   
3       004  line_items  93         allocated                    2   

  attributes.various_other_data  
0                           etc  
1                           etc  
2                           etc  
2                           etc  
3                           etc  
3                           etc

如果只需要处理id列和id值是唯一的,则创建helper Series并使用Series.map

s = df.set_index('id')['sub-array'].apply(ast.literal_eval).explode().str.get('id')
df['id_parent'] = df['id'].map(s)
wljmcqd8

wljmcqd82#

因此,您可以通过以下方式生成主数组:

import pandas as pd

# Sample data
saledata = pd.DataFrame({
    'id': ['001', '002', '003', '004'],
    'sub-array': [[{'type': 'line_items', 'id': '78', 'attributes': {'status': 'allocated', 'quantity': 1, 'various_other_data': 'etc'}}],
                  [{'type': 'line_items', 'id': '80', 'attributes': {'status': 'allocated', 'quantity': 2, 'various_other_data': 'etc'}}],
                  [{'type': 'line_items', 'id': '85', 'attributes': {'status': 'allocated', 'quantity': 1, 'various_other_data': 'etc'}},
                   {'type': 'line_items', 'id': '86', 'attributes': {'status': 'allocated', 'quantity': 1, 'various_other_data': 'etc'}}],
                  [{'type': 'line_items', 'id': '92', 'attributes': {'status': 'allocated', 'quantity': 2, 'various_other_data': 'etc'}},
                   {'type': 'line_items', 'id': '93', 'attributes': {'status': 'allocated', 'quantity': 2, 'various_other_data': 'etc'}}]
                 ]
})

itemdata = pd.DataFrame({
    'type': ['line_item', 'line_item', 'line_item', 'line_item', 'line_item', 'line_item'],
    'id': ['78', '80', '85', '86', '92', '93'],
    'attributes.status': ['allocated', 'allocated', 'allocated', 'allocated', 'allocated', 'allocated'],
    'attributes.quantity': [1, 2, 1, 1, 2, 2],
    'attributes.various_other_data': ['etc', 'etc', 'etc', 'etc', 'etc', 'etc']
})
In [4]: import numpy as np                                                                                                 

In [5]: item_id2sale_ids = {i_id: np.where(df['sub-array'].apply(lambda x: any(item['id'] == i_id for item in x))) for i_id
   ...:  in itemdata['id']}                                                                                                

In [6]: item_id2sale_ids                                                                                                   
Out[6]: 
{'78': (array([0], dtype=int32),),
 '80': (array([1], dtype=int32),),
 '85': (array([2], dtype=int32),),
 '86': (array([2], dtype=int32),),
 '92': (array([3], dtype=int32),),
 '93': (array([3], dtype=int32),)}

相关问题