在作为字典列表的数据框列中,如何将值与将每个嵌套键作为新列的逗号连接起来?

In a dataframe column that is a list of dictionaries, how to join values with a comma having each nested key as a new column?

我有一个看起来像这样的数据框

╔══════╦══════╦══════════════════════════════════╦═══════════════════════╗
║ ID   ║ Name ║ Pets                             ║ CareCenter            ║
╠══════╬══════╬══════════════════════════════════╬═══════════════════════╣
║ 1    ║ John ║ [{'Name':'Alvin','Breed':'Dog'}, ║ {'Name':'PET SHOP 1'} ║
║      ║      ║ {'Name':'Rex','Type':'Cat'}]     ║                       ║
╠══════╬══════╬══════════════════════════════════╬═══════════════════════╣
║ 10   ║ Mary ║ {'Name':'Rose','Type':'Cat'}     ║ {'Name':'PET SHOP 2'} ║
╠══════╬══════╬══════════════════════════════════╬═══════════════════════╣
║ 1234 ║ Joe  ║ {'Name':'Max','Type':'Bird'}     ║ {'Name':'PET SHOP 3'} ║
╚══════╩══════╩══════════════════════════════════╩═══════════════════════╝
  1. 我遍历每一列以检查其类型。

  2. 如果它不是对象(例如字符串、整数等),我将保持不变。

  3. 如果是对象,则:

    3.1) 我得到第一行并得到每列的类型

    3.2) 如果该列是一个对象和一个字典(只有一个项目)我得到这个 df

╔══════╦═══════════════════════╗
║ ID   ║ CareCenter            ║
╠══════╬═══════════════════════╣
║ 1    ║ {'Name':'PET SHOP 1'} ║
╠══════╬═══════════════════════╣
║ 10   ║ {'Name':'PET SHOP 2'} ║
╠══════╬═══════════════════════╣
║ 1234 ║ {'Name':'PET SHOP 3'} ║
╚══════╩═══════════════════════╝

然后我在单项字典列上应用 json_normalize。

╔══════╦═══════════════════════╦═══════════════════════╗
║ ID   ║ CareCenter            ║ CareCenter_Name       ║
╠══════╬═══════════════════════╬═══════════════════════╣
║ 1    ║ {'Name':'PET SHOP 1'} ║ PET SHOP 1            ║
╠══════╬═══════════════════════╬═══════════════════════╣
║ 10   ║ {'Name':'PET SHOP 2'} ║ PET SHOP 2            ║
╠══════╬═══════════════════════╬═══════════════════════╣
║ 1234 ║ {'Name':'PET SHOP 3'} ║ PET SHOP 3            ║
╚══════╩═══════════════════════╩═══════════════════════╝

然后将其连接回 ID 列上的原始 df。使用与原始列名称连接的键名称并删除原始列。

╔══════╦══════╦══════════════════════════════════╦═════════════════╗
║ ID   ║ Name ║ Pets                             ║ CareCenter_Name ║
╠══════╬══════╬══════════════════════════════════╬═════════════════╣
║ 1    ║ John ║ [{'Name':'Alvin','Breed':'Dog'}, ║ PET SHOP 1      ║
║      ║      ║ {'Name':'Rex','Type':'Cat'}]     ║                 ║
╠══════╬══════╬══════════════════════════════════╬═════════════════╣
║ 10   ║ Mary ║ {'Name':'Rose','Type':'Cat'}     ║ PET SHOP 2      ║
╠══════╬══════╬══════════════════════════════════╬═════════════════╣
║ 1234 ║ Joe  ║ {'Name':'Max','Type':'Bird'}     ║ PET SHOP 3      ║
╚══════╩══════╩══════════════════════════════════╩═════════════════╝

3.3) 如果该列是字典列表,我会像这样创建一个新的 df,只需要 ID 和在位列:

╔══════╦══════════════════════════════════╗
║ ID   ║ Pets                             ║
╠══════╬══════════════════════════════════╣
║ 1    ║ [{'Name':'Alvin','Breed':'Dog'}, ║
║      ║ {'Name':'Rex','Type':'Cat'}]     ║
╠══════╬══════════════════════════════════╣
║ 10   ║ {'Name':'Rose','Type':'Cat'}     ║
╠══════╬══════════════════════════════════╣
║ 1234 ║ {'Name':'Max','Type':'Bird'}     ║
╚══════╩══════════════════════════════════╝

但是我不知道如何将每个嵌套键的值连接到新列中,我正在寻找类似这样的东西,之后我可以从那里获取它并将其连接回原始 df。连接字符串的顺序并不重要,只要它们在正确的列中即可

╔══════╦═══════════╦═══════════╗
║ ID   ║ Pets_Name ║ Pets_Type ║
╠══════╬═══════════╬═══════════╣
║ 1    ║ Alvin,Rex ║ Dog,Cat   ║
╠══════╬═══════════╬═══════════╣
║ 10   ║ Rose      ║ Cat       ║
╠══════╬═══════════╬═══════════╣
║ 1234 ║ Name      ║ Bird      ║
╚══════╩═══════════╩═══════════╝

到目前为止,这是我的代码:

for column in data_df:
        if data_df.dtypes[column] == "object":
            new = data_df[['Id', column]].copy()
            new = new.dropna(subset = [column])
            a = (new.sample(1).applymap(type) == list).all()
            islist = False
            for i,v in a.items():
                if(v==True and i==column):
                    islist = True
            if(islist==True):
                for c in(json_normalize(new[column].sample(1).iloc[0])):
******STUCK*****    new = new.join(','.join({v for x in new[column] for y in x for k,v in y.items() if k==c}))  ****** STUCK ****
            else:
                new = new.join(json_normalize(new[column]))
            new = new.drop(column,axis=1)
            new = new.add_prefix(column + '_')
            #data_df=data_df.join(new, on='Id',how='left')
            data_df=pd.merge(data_df, new, how='left', left_on='Id', right_on=column + '_Id' )
            data_df = data_df.drop(column, 1)
            data_df = data_df.drop(column + '_Id', 1)

编辑: 这将是我正在寻找的最后一个 table

╔══════╦══════╦═══════════╦═══════════╦═════════════════╗
║ ID   ║ Name ║ Pets_Name ║ Pets_Type ║ CareCenter_Name ║
╠══════╬══════╬═══════════╬═══════════╬═════════════════╣
║ 1    ║ John ║ Alvin,Rex ║ Dog,Cat   ║ PET SHOP 1      ║
╠══════╬══════╬═══════════╬═══════════╬═════════════════╣
║ 10   ║ Mary ║ Rose      ║ Cat       ║ PET SHOP 2      ║
╠══════╬══════╬═══════════╬═══════════╬═════════════════╣
║ 1234 ║ Joe  ║ Max       ║ Bird      ║ PET SHOP 3      ║
╚══════╩══════╩═══════════╩═══════════╩═════════════════╝

提前感谢您给我的任何指示,

最终编辑:

这是我在@BEN_YO

帮助下的工作代码
for column in data_df:
        #mytype = data_df.dtypes[column]
        mn = data_df.sample(1).applymap(type)
        mytype = mn[column].values[0]
        if mytype is dict or mytype is list:
            new = data_df[['Id', column]].copy()
            new = new.dropna(subset = [column])
            a = (new.sample(1).applymap(type) == list).all()
            islist = False
            for i,v in a.items():
                if(v==True and i==column):
                    islist = True
            if(islist==True):
                for c in(json_normalize(new[column].sample(1).iloc[0])):
                    #new = new.join(','.join({v for x in new[column] for y in x for k,v in y.items() if k==c}))
                    new = new.join(new[column].explode().apply(pd.Series).groupby(level=0)[[c]].agg(','.join))
                    #print(column)
            else:
                new = new.join(json_normalize(new[column]))
            new = new.drop(column,axis=1)
            new = new.add_prefix(column + '_')
            #data_df=data_df.join(new, on='Id',how='left')
            data_df=pd.merge(data_df, new, how='left', left_on='Id', right_on=column + '_Id' )
            data_df = data_df.drop(column, 1)
            data_df = data_df.drop(column + '_Id', 1)

试试 explode

out = df.join(df['Pets'].explode().apply(pd.Series).groupby(level=0)[['Name']].agg(','.join))