Python 使用列表值解包dataframe列
假设我们下面有Python 使用列表值解包dataframe列,python,pandas,dataframe,Python,Pandas,Dataframe,假设我们下面有df_orig,列B包括不同长度的行列表。在B中的每一行中,X的值是唯一的。X的每个唯一值可能出现在B的每一行中,也可能不出现。我认为这个例子最能说明问题 import pandas as pd df_orig = pd.DataFrame({ 'A': ['a', 'b', 'c', 'd', 'e'], 'B': [ [{'X': 'abc'}], [{'X': 'abc'}, {'X': 'dtf'}, {'X': 'kju'
df_orig
,列B
包括不同长度的行列表。在B
中的每一行中,X
的值是唯一的。X
的每个唯一值可能出现在B
的每一行中,也可能不出现。我认为这个例子最能说明问题
import pandas as pd
df_orig = pd.DataFrame({
'A': ['a', 'b', 'c', 'd', 'e'],
'B': [
[{'X': 'abc'}],
[{'X': 'abc'}, {'X': 'dtf'}, {'X': 'kju'}],
[{'X': 'abc'}, {'X': 'dtf'}],
[{'X': 'abc'}, {'X': 'dtf'}, {'X': 'kju'}, {'X': 'etr'}],
[]
]
})
df_orig
A B
0 a [{'X': 'abc'}]
1 b [{'X': 'abc'}, {'X': 'dtf'}, {'X': 'kju'}]
2 c [{'X': 'abc'}, {'X': 'dtf'}]
3 d [{'X': 'abc'}, {'X': 'dtf'}, {'X': 'kju'}, {'X': 'etr'}]
4 e []
我想要的是“解包”B
,以便X
的每个唯一值都有自己的列,并使用0/1
编码指示该值(列名)是否存在于每行中。所需的dataframe
,df_des
,如下所示:
df_des
A abc dtf kju etr
0 a 1 0 0 0
1 b 1 1 1 0
2 c 1 1 0 0
3 d 1 1 1 1
4 e 0 0 0 0
您可以使用数据帧构造函数,使用
applymap
、get\u dummies
和join
返回每个单元格中字典的值:
m = (pd.DataFrame(df_orig['B'].tolist()).applymap(lambda x:
[*x.values()][0] if isinstance(x,dict) else x))
final = df_orig[['A']].join(
pd.get_dummies(m).groupby(lambda x: x.split('_')[-1],axis=1).max())
编辑:
要连接多个列,您可以退出列B
,然后按如下所示进行连接:
m = (pd.DataFrame(df_orig.pop('B').tolist()).applymap(lambda x:
[*x.values()][0] if isinstance(x,dict) else x))
final = df_orig.join(
pd.get_dummies(m).groupby(lambda x: x.split('_')[-1],axis=1).max())
您可以使用数据帧构造函数,使用
applymap
、get\u dummies
和join
返回每个单元格中字典的值:
m = (pd.DataFrame(df_orig['B'].tolist()).applymap(lambda x:
[*x.values()][0] if isinstance(x,dict) else x))
final = df_orig[['A']].join(
pd.get_dummies(m).groupby(lambda x: x.split('_')[-1],axis=1).max())
编辑:
要连接多个列,您可以退出列B
,然后按如下所示进行连接:
m = (pd.DataFrame(df_orig.pop('B').tolist()).applymap(lambda x:
[*x.values()][0] if isinstance(x,dict) else x))
final = df_orig.join(
pd.get_dummies(m).groupby(lambda x: x.split('_')[-1],axis=1).max())
另一种办法:
#extract the data from the dictionary
df_orig['C'] = df_orig.B.apply(lambda x: [i['X'] for i in x])
#convert list to string
df_orig.C = df_orig.C.apply(lambda x: ','.join(x))
create dummies from split string
dum = pd.get_dummies(df_orig.C.str.split(',', expand=True)).drop('0_',axis=1)
#strip numbers off the columns
dum.columns = dum.columns.str.replace('\d_','')
#join dummies back to parent dataframe
pd.concat([df_orig['A'], dum], axis=1).filter(['A','abc','dtf','etr','kju'])
A abc dtf etr kju
0 a 1 0 0 0
1 b 1 1 0 1
2 c 1 1 0 0
3 d 1 1 1 1
4 e 0 0 0 0
另一种办法:
#extract the data from the dictionary
df_orig['C'] = df_orig.B.apply(lambda x: [i['X'] for i in x])
#convert list to string
df_orig.C = df_orig.C.apply(lambda x: ','.join(x))
create dummies from split string
dum = pd.get_dummies(df_orig.C.str.split(',', expand=True)).drop('0_',axis=1)
#strip numbers off the columns
dum.columns = dum.columns.str.replace('\d_','')
#join dummies back to parent dataframe
pd.concat([df_orig['A'], dum], axis=1).filter(['A','abc','dtf','etr','kju'])
A abc dtf etr kju
0 a 1 0 0 0
1 b 1 1 0 1
2 c 1 1 0 0
3 d 1 1 1 1
4 e 0 0 0 0
好了:
import pandas as pd
from sklearn.preprocessing import MultiLabelBinarizer
df_orig = pd.DataFrame({
'A': ['a', 'b', 'c', 'd', 'e'],
'B': [
[{'X': 'abc'}],
[{'X': 'abc'}, {'X': 'dtf'}, {'X': 'kju'}],
[{'X': 'abc'}, {'X': 'dtf'}],
[{'X': 'abc'}, {'X': 'dtf'}, {'X': 'kju'}, {'X': 'etr'}],
[]
]
})
b = []
for x in df_orig.B:
dummy = []
for y in x:
dummy.append(y['X'])
b.append(dummy)
b = pd.Series(b)
mlb = MultiLabelBinarizer()
res = pd.DataFrame(mlb.fit_transform(b),columns=mlb.classes_,index=b.index)
df_orig = df_orig.drop(['B'],axis=1)
df_res = pd.concat([df_orig,res],axis=1)
print(df_res)
output:
A abc dtf etr kju
0 a 1 0 0 0
1 b 1 1 0 1
2 c 1 1 0 0
3 d 1 1 1 1
4 e 0 0 0 0
首先,将B列设置为列表,然后使用multilabelbinarizer对列表进行热编码。好了:
import pandas as pd
from sklearn.preprocessing import MultiLabelBinarizer
df_orig = pd.DataFrame({
'A': ['a', 'b', 'c', 'd', 'e'],
'B': [
[{'X': 'abc'}],
[{'X': 'abc'}, {'X': 'dtf'}, {'X': 'kju'}],
[{'X': 'abc'}, {'X': 'dtf'}],
[{'X': 'abc'}, {'X': 'dtf'}, {'X': 'kju'}, {'X': 'etr'}],
[]
]
})
b = []
for x in df_orig.B:
dummy = []
for y in x:
dummy.append(y['X'])
b.append(dummy)
b = pd.Series(b)
mlb = MultiLabelBinarizer()
res = pd.DataFrame(mlb.fit_transform(b),columns=mlb.classes_,index=b.index)
df_orig = df_orig.drop(['B'],axis=1)
df_res = pd.concat([df_orig,res],axis=1)
print(df_res)
output:
A abc dtf etr kju
0 a 1 0 0 0
1 b 1 1 0 1
2 c 1 1 0 0
3 d 1 1 1 1
4 e 0 0 0 0
首先,将B列设置为列表,然后使用multilabelbinarizer对列表进行热编码。您的解决方案非常简洁。我想知道这是否取决于
A
?我问这个问题的原因是,实际上除了A
之外还有很多列,因此理想情况下,我只需要将新列附加到原始df
@CHRD,如果有很多列要加入,我已经编辑了答案。您的解决方案非常简洁。我想知道这是否取决于A
?我问这个问题的原因是,实际上除了A
之外还有很多列,因此理想情况下,我只需要将新列附加到原始df
@CHRD,如果有很多列要加入,我已经编辑了答案