我有一个dataframe,每一行都有一个列表值
id list_of_value
0 ['a','b','c']
1 ['d','b','c']
2 ['a','b','c']
3 ['a','b','c']
我必须计算一行的分数,然后对照所有其他行
例如:
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
在id 0和id 1,2,3之间重复步骤2,3,对所有id重复相同操作。
并创建一个nxn数据帧;例如:
- 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
现在我的代码只有一个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,))
有更好的方法吗?我可以只编写一个apply函数,而不是执行for循环迭代吗。 我能快点吗
如果数据不太大,可以使用
get_dummies
对值进行编码并执行矩阵乘法:输出:
更新:下面是对代码的简短解释。其主要思想是将给定列表转换为一个热编码列表:
一旦我们有了它,两行的交集的大小,比如说,
0
和1
就是它们的点积,因为一个字符属于这两行,当且仅当它在这两行中都由1
表示记住这一点,首先使用
将每个单元格转换为一个系列并连接所有这些系列。输出:
现在,我们在该系列上使用
pd.get_dummies
将其转换为一个热编码数据帧:如您所见,每个值都有自己的行。由于我们希望将属于同一原始行的数据合并到一行中,因此我们可以通过原始索引对它们求和。因此
给出所需的二进制编码数据帧。下一行
正如您的逻辑:
s.dot(s.T)
按行计算点积,然后.div(s.sum(1))
按行除以计数试试这个
输出
您也可以按如下方式进行操作
对集合
s_list
的列表使用嵌套列表理解。在列表理解中,使用intersection
操作检查重叠并获得每个结果的长度。最后,构造数据帧并将其除以df.list_of_value
中每个列表的长度如果每个列表中都有重复的值,则应使用
collections.Counter
而不是set
。我将样本数据id=0更改为['a','a','c']
,将id=1更改为['d','b','a']
相关问题 更多 >
编程相关推荐