在作为字典列表的数据框列中,如何将值与将每个嵌套键作为新列的逗号连接起来?
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'} ║
╚══════╩══════╩══════════════════════════════════╩═══════════════════════╝
我遍历每一列以检查其类型。
如果它不是对象(例如字符串、整数等),我将保持不变。
如果是对象,则:
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))
我有一个看起来像这样的数据框
╔══════╦══════╦══════════════════════════════════╦═══════════════════════╗ ║ 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'} ║ ╚══════╩══════╩══════════════════════════════════╩═══════════════════════╝
我遍历每一列以检查其类型。
如果它不是对象(例如字符串、整数等),我将保持不变。
如果是对象,则:
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))