拯救pandas计划(19) 您所在的位置:网站首页 tableau的count函数 拯救pandas计划(19)

拯救pandas计划(19)

2023-06-06 14:47| 来源: 网络整理| 查看: 265

拯救pandas计划(19)——使用自定义方法计算两列的相似度

最近发现周围的很多小伙伴们都不太乐意使用pandas,转而投向其他的数据操作库,身为一个数据工作者,基本上是张口pandas,闭口pandas了,故而写下此系列以让更多的小伙伴们爱上pandas。

系列文章说明:

系列名(系列文章序号)——此次系列文章具体解决的需求

平台:

windows 10python 3.8pandas >=1.2.4/ 数据需求

最近在互联网遨游时偶然发现一道很有趣的pandas实例训练题目,题目距今已发布很久,也已经有人为此解答过了,说:有一组数据,每列分别记录着样品的各个指标情况,欲对每个数据各个指标进行计算,求各个样品之间的指标差值的绝对值的总和最小的对应的几个样品,如:a样品:[10.0, 9.0, 7.5, 8.6],b样品:[11.2, 8.7, 6.4, 5.5]之间的相似度计算为:|10.0-11.2|+|9.0-8.7|+|7.5-6.4|+|8.6-5.5|。

对应位置相减取绝对值后再相加,为每个样品对其余样品进行计算,求得所有样品的与其相似度最小的5个其他样品。

根据上述描述,构造一组随机数据:

import numpy as np import pandas as pd np.random.seed(2022) data = np.clip(np.random.normal(loc=70, scale=15, size=600).round(2), 0, 100).reshape(60, 10) df = pd.DataFrame(data, columns=list('abcdefghij'), index=[f'测试_{i}' for i in range(1, 61)])

数据大小为:60*10,浮点型类型。

拯救pandas计划(19)——使用自定义方法计算两列的相似度_大数据

/ 需求处理方法一:笛卡尔积

先计算每个样品的交叉数据,再分组获取组内排名在上的5个数据。

这个方法是该题目下方解答者大佬的方法,其使用的方法进行笛卡尔乘积非常有意思。

df = df.reset_index().rename(columns={'index': '名称'}) # 设置辅助列 df['one'] = 1 # merge自身,以one列作为key参数合并数据框 df_merge = pd.merge(left=df, right=df, left_on='one', right_on='one')

原数据大小为60*10,乘积后为3600行,内存占用大小相比处理前大了不少,如果数据过大,在处理方面,耗时上会显著增加。

拯救pandas计划(19)——使用自定义方法计算两列的相似度_大数据_02

暂且不考虑数据量的影响,继续处理。

# 剔掉名称列和one列 columns = list(df.columns) columns.remove('名称') columns.remove('one') def sim_fun(row): sim_value = 0.0 for col in columns: sim_value += abs(round(row[col+'_x'] - row[col+'_y'], 2)) return round(sim_value, 2) # 求出每个样品之间的相似值 df_merge['sim'] = df_merge.apply(sim_fun, axis=1) df_merge = df_merge[df_merge['名称_x'] != df_merge['名称_y']].copy() # 获取每个样品与其相似值最小的5个样品 def get_top_sims(df_sub): df_sort = df_sub.sort_values('sim').head(5) names = ','.join(df_sort['名称_y']) sims = ','.join(df_sort['sim'].astype(str)) return pd.Series({'names': names, 'sims': sims}) df_result = df_merge.groupby('名称_x').apply(get_top_sims)

通过复现解答大佬的代码如上,顺利返回了相似度前五的数据框。可以看到在60条数据中使用笛卡尔积进行计算,耗用时间是可以接受的。

拯救pandas计划(19)——使用自定义方法计算两列的相似度_大数据_03

方法二:将每一行数据与原数据直接相减,利用pandas特性求和

在方法一中能注意到数据处理上稍有繁琐,将数据扩容再处理,且数据的差值为逐个计算。仔细理解数据,可以利用数组的广播特性进行处理。

def get_sims(s): # 注意:此处的df为全局变量 df_sim = (df - s).abs().sum(axis=1).round(2) df_sim.pop(s.name) df_sim = df_sim.sort_values(ascending=False).head(5).astype(str) return pd.Series({'names': ','.join(df_sim.index), 'sims': ','.join(df_sim.values)}) # apply按行遍历数据,使其他行与该行进行数据计算 df_result = df.apply(get_sims, axis=1)

使用广播的特性将方法一中的函数优化为get_sims函数,在计算效率上也大大提高。

拯救pandas计划(19)——使用自定义方法计算两列的相似度_机器学习_04

/ 总结

本文通过了解题目目的及其他解答者的想法,根据自身掌握的pandas技巧对题目进行分析处理,在一定程度上减少数据计算的冗余度,满足数据需求,如对本文有不理解之处,尽可发言表述自己的想法。

独乐乐不如众乐乐。

于二零二二年六月二十一日作



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有