将 Pandas 数据框列从列表展平到它们自己的特定列

问题描述

我有一个 Pandas 数据框,其中有一列包含一个包含信息的数组列表。它看起来像这样:

id   basket                                       date
c1   [{'product_id': 'P64','price': 1146}]       2020-08-11                                     
c2   [{'product_id': 'P44','price': 1426},2020-08-11 
      {'product_id': 'P49','price': 1108}]                                          
c3   [{'product_id': 'P60','price': 39},'price': 1155},{'product_id': 'P46','price': 178}]

我想将篮子列展平,使其看起来像这样:

id   product_id  price     date
c1   P64         1146      2020-08-11                                     
c2   P44         1426      2020-08-11
c2   P49         1108      2020-08-11
c3   P60           39      2020-08-11
c3   P49         1155      2020-08-11
c3   P46          178      2020-08-11

我似乎无法弄清楚,任何帮助将不胜感激。

解决方法

Split (explode) pandas dataframe string entry to separate rows 有爆炸功能,很棒。

# ---- MAKE MODELS ---- #
NUMBER_OF_MODELS = 4
models = []
for i in range(NUMBER_OF_MODELS):
    model = keras.models.Sequential(name=f'{i}')

    model.add(keras.layers.Dense(8,activation='relu',input_shape=df_train['features'].values.shape[-1:]))
    model.add(keras.layers.Dense(3,activation='softmax'))

    model.compile(optimizer=keras.optimizers.Adam(),loss=keras.losses.CategoricalCrossentropy(),metrics=[keras.metrics.CategoricalAccuracy()])

    model.summary()
    models.append(model)
# --------------------- #

# ---- TRAIN MODELS ---- #
histories = []
for model in models:
    with tf.device('/cpu:0'):
        history = model.fit(x=df_train['features'].values,y=df_train['labels'].values,validation_data=(df_val['features'].values,df_val['labels'].values),batch_size=512,epochs=100,verbose=0)
        histories.append(history)
# ---------------------- #

你会打电话

def explode(df,lst_cols,fill_value='',preserve_index=False):
    # make sure `lst_cols` is list-alike
    if (lst_cols is not None
        and len(lst_cols) > 0
        and not isinstance(lst_cols,(list,tuple,np.ndarray,pd.Series))):
        lst_cols = [lst_cols]
    # all columns except `lst_cols`
    idx_cols = df.columns.difference(lst_cols)
    # calculate lengths of lists
    lens = df[lst_cols[0]].str.len()
    # preserve original index values    
    idx = np.repeat(df.index.values,lens)
    # create "exploded" DF
    res = (pd.DataFrame({
                col:np.repeat(df[col].values,lens)
                for col in idx_cols},index=idx)
             .assign(**{col:np.concatenate(df.loc[lens>0,col].values)
                            for col in lst_cols}))
    # append those rows that have empty lists
    if (lens == 0).any():
        # at least one list in cells is empty
        res = (res.append(df.loc[lens==0,idx_cols],sort=False)
                  .fillna(fill_value))
    # revert the original index order
    res = res.sort_index()
    # reset index if requested
    if not preserve_index:        
        res = res.reset_index(drop=True)
    return res

那么你就必须将键和值拆分成单独的列,这 Explode dict from Pandas column 就是这样做的。

,

试试:

x = [pd.DataFrame(i) for i in df['basket']]
for idx,data in enumerate(x):
    data['id']=df.iloc[idx]['id']
    data['date']=df.iloc[idx]['date']
df2 = pd.concat(x).reset_index(drop=True)

df2:

    product_id  price   id  date
0   P64         1146    c1  2020-08-11
1   P44         1426    c2  2020-08-11 
2   P49         1108    c2  2020-08-11 
3   P60         39      c3  2020-08-11
4   P49         1155    c3  2020-08-11
5   P46         178     c3  2020-08-11
,

您可以使用:

import pandas
from pandas import json_normalize

combined = pandas.concat([json_normalize(df['basket']) for column in df])

内联 for 循环为列篮中的每个键创建一个对象列表。然后,使用 pandas.concat,将每个列表连接到一个数据帧中并将其返回组合。 我用它来扁平化 MongoDb 查询结果。之后,您必须添加其他列。