使用列表值解包dataframe列

2024-05-20 20:26:28 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我们在下面有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编码指示该值(列名)是否存在于每一行中。所需的dataframedf_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

Tags: importdataframepandas编码df列表as例子
3条回答

您可以使用dataframe构造函数并返回每个单元格中的字典值,包括applymapget_dummiesjoin

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())

   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对列表进行热编码

相关问题 更多 >