Sri*_*mar 11 python numpy pandas
我有数据框,每一行都有一个列表值。
id list_of_value
0 ['a','b','c']
1 ['d','b','c']
2 ['a','b','c']
3 ['a','b','c']
Run Code Online (Sandbox Code Playgroud)
我必须用一行和所有其他行计算分数
例如:
Step 1: Take value of id 0: ['a','b','c'],
Step 2: find the intersection between id 0 and id 1 ,
resultant = ['b','c']
Step 3: Score Calculation => resultant.size / id.size
Run Code Online (Sandbox Code Playgroud)
在 id 0 和 id 1,2,3 之间重复步骤 2,3,对于所有 id 都类似。
并创建一个 N x N 数据框;像这样:
- 0 1 2 3
0 1 0.6 1 1
1 1 1 1 1
2 1 1 1 1
3 1 1 1 1
Run Code Online (Sandbox Code Playgroud)
现在我的代码只有一个 for 循环:
def scoreCalc(x,queryTData):
#mathematical calculation
commonTData = np.intersect1d(np.array(x),queryTData)
return commonTData.size/queryTData.size
ids = list(df['feed_id'])
dfSim = pd.DataFrame()
for indexQFID in range(len(ids)):
queryTData = np.array(df.loc[df['id'] == ids[indexQFID]]['list_of_value'].values.tolist())
dfSim[segmentDfFeedIds[indexQFID]] = segmentDf['list_of_value'].apply(scoreCalc,args=(queryTData,))
Run Code Online (Sandbox Code Playgroud)
有一个更好的方法吗?我可以只写一个应用函数而不是进行 for 循环迭代吗?我可以让它更快吗?
如果您的数据不是太大,您可以使用get_dummies对值进行编码并进行矩阵乘法:
s = pd.get_dummies(df.list_of_value.explode()).sum(level=0)
s.dot(s.T).div(s.sum(1))
Run Code Online (Sandbox Code Playgroud)
输出:
0 1 2 3
0 1.000000 0.666667 1.000000 1.000000
1 0.666667 1.000000 0.666667 0.666667
2 1.000000 0.666667 1.000000 1.000000
3 1.000000 0.666667 1.000000 1.000000
Run Code Online (Sandbox Code Playgroud)
更新:这是代码的简短说明。主要思想是将给定的列表转换为单热编码:
a b c d
0 1 1 1 0
1 0 1 1 1
2 1 1 1 0
3 1 1 1 0
Run Code Online (Sandbox Code Playgroud)
一旦我们有,这两行的交集的大小,说,0和1仅仅是他们的点积,是因为角色属于当且仅当它被表示为两行1两。
考虑到这一点,首先使用
df.list_of_value.explode()
Run Code Online (Sandbox Code Playgroud)
将每个单元格变成一个系列并连接所有这些系列。输出:
0 a
0 b
0 c
1 d
1 b
1 c
2 a
2 b
2 c
3 a
3 b
3 c
Name: list_of_value, dtype: object
Run Code Online (Sandbox Code Playgroud)
现在,我们使用pd.get_dummies该系列将其转换为单热编码数据帧:
a b c d
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
1 0 0 0 1
1 0 1 0 0
1 0 0 1 0
2 1 0 0 0
2 0 1 0 0
2 0 0 1 0
3 1 0 0 0
3 0 1 0 0
3 0 0 1 0
Run Code Online (Sandbox Code Playgroud)
如您所见,每个值都有自己的行。由于我们要将属于同一原始行的那些合并为一行,因此我们可以通过原始索引将它们相加。因此
s = pd.get_dummies(df.list_of_value.explode()).sum(level=0)
Run Code Online (Sandbox Code Playgroud)
给出我们想要的二进制编码数据帧。下一行
s.dot(s.T).div(s.sum(1))
Run Code Online (Sandbox Code Playgroud)
就像你的逻辑一样:s.dot(s.T)按行计算点积,然后.div(s.sum(1))按行除以计数。
| 归档时间: |
|
| 查看次数: |
1092 次 |
| 最近记录: |