Pandas -对逗号分隔的要素名称列应用函数,并将权重存储在单独的对应列中

vaqhlq81  于 2023-02-17  发布在  其他
关注(0)|答案(4)|浏览(119)

考虑以下 Dataframe df,其中feature列是数据集中以逗号分隔的要素名称字符串(df可能很大)。

index    features
1        'f1'  
2        'f1, f2'
3        'f1, f2, f3'

我还有一个函数get_weights,它接受逗号分隔的特征名称字符串,计算并返回一个列表,其中包含每个给定权重的权重,实现细节并不重要,为了简单起见,让我们考虑该函数为每个特征返回相等的权重:

import numpy as np
def get_weights(features):
   features = features.split(', ')
   return np.ones(len(features)) / len(features)

使用panda,我如何在df上应用get_weights,并在新的 Dataframe 中获得如下结果:

index   f1     f2    f3 
1       1      0      0
2       0.5    0.5    0
3       0.33   0.33   0.33

也就是说,在所得到的 Dataframe 中,df.features中的特征被转换成列,所述列包含每行该特征的权重。

m3eecexj

m3eecexj1#

备选案文1

考虑到目标是将函数应用于 Dataframe 功能,可以按如下方式使用pandas.Series.apply

df = df['features'].apply(lambda x: pd.Series(get_weights(x)))

[Out]:

          0         1         2
0  1.000000       NaN       NaN
1  0.500000  0.500000       NaN
2  0.333333  0.333333  0.333333

然而,为了获得理想的输出,仍然有几件事要做。
首先,调整前面的操作,用0填充NaN

df = df['features'].apply(lambda x: pd.Series(get_weights(x))).fillna(0)

[Out]:

          0         1         2
0  1.000000  0.000000  0.000000
1  0.500000  0.500000  0.000000
2  0.333333  0.333333  0.333333

第二,希望列的名称分别为f1f2f3

df = df['features'].apply(lambda x: pd.Series(get_weights(x))).fillna(0).rename(columns={0: 'f1', 1: 'f2', 2: 'f3'})

[Out]:

         f1        f2        f3
0  1.000000  0.000000  0.000000
1  0.500000  0.500000  0.000000
2  0.333333  0.333333  0.333333

现在,从前面的操作开始,由于缺少从1开始的列index,因此可以简单地执行以下操作

df['index'] = df.index + 1

[Out]:

   index        f1        f2        f3
0      1  1.000000  0.000000  0.000000
1      2  0.500000  0.500000  0.000000
2      3  0.333333  0.333333  0.333333

最后,如果目标是使索引列成为 Dataframe 的索引,则可以使用pandas.DataFrame.set_index,如下所示

df = df.set_index('index')

[Out]:

             f1        f2        f3
index                              
1      1.000000  0.000000  0.000000
2      0.500000  0.500000  0.000000
3      0.333333  0.333333  0.333333

备选案文2

如果不想使用.apply()(按照下面的第一个注解),另一个选项和满足所有要求的一行程序将创建一个新的 Dataframe ,如下所示

df_new = pd.DataFrame([get_weights(x) for x in df['features']]).fillna(0).rename(columns={0: 'f1', 1: 'f2', 2: 'f3'}).set_index(pd.Series(range(1, len(df)+1), name='index'))

[Out]:

             f1        f2        f3
index                              
1      1.000000  0.000000  0.000000
2      0.500000  0.500000  0.000000
3      0.333333  0.333333  0.333333

注:

s3fp2yjn

s3fp2yjn2#

您可以用途:

df2 = (pd.DataFrame([get_weights(s) for s in df['features']], index=df.index)
         .fillna(0).rename(columns=lambda x: f'f{x+1}')
       )
out = df.drop(columns='features').join(df2)

输出:

index        f1        f2        f3
0      1  1.000000  0.000000  0.000000
1      2  0.500000  0.500000  0.000000
2      3  0.333333  0.333333  0.333333
lyr7nygr

lyr7nygr3#

使用函数get_dummies from panda,您可以执行以下操作:

# 0- Let's define an example pandas DataFrame:

df = pd.DataFrame(
    {
        "features": ["f1", "f1, f2", "f1, f2, f3", "f1, f4"]
    }
)

# 1- Convert column of strings into Series of lists:

aux_series = df["features"].str.split(", ")

# 2- Use get_dummies function, transpose the result and fill NaN's

aux_df = pd.concat([pd.get_dummies(aux_series[i]).sum() for i in df.index], axis=1).T.fillna(0)

# 3- Get the 'weight' of each value diving by its row summatory

output_df = aux_df.div(aux_df.sum(axis=1), axis=0)

# 4- Print the result:

print(output_df)

[Out]:

         f1        f2        f3   f4
0  1.000000  0.000000  0.000000  0.0
1  0.500000  0.500000  0.000000  0.0
2  0.333333  0.333333  0.333333  0.0
3  0.500000  0.000000  0.000000  0.5
vngu2lb8

vngu2lb84#

df2=df1.features.str.get_dummies(sep=',')
df2.T.mul((df2.sum(axis=1).rdiv(1)).round(2)).T

输出:

f2    f3    f1
0  0.00  0.00  1.00
1  0.50  0.00  0.50
2  0.33  0.33  0.33

相关问题