如何在Pandas中无循环实现基于编码属性的DataFrame除法
无需循环实现按属性匹配的DataFrame除法
嘿,这个需求完全可以用pandas的向量化操作搞定,不用写for循环~ 咱们先理清楚数据之间的对应关系,然后利用pandas的索引对齐特性一步到位。
先明确数据关联
你的三个DataFrame关系是:
df的每一列(颜色:Green/Blue/Red/Yellow)对应db里的一个属性(Small/Medium/Large)df1的列是属性,每个属性对应一组除数- 最终要把
df中每一列的数值,除以df1中对应属性列的数值
无循环实现方案
核心思路是:先把df的列名映射成对应的属性,让df1的除数列和df的数值列顺序完全对齐,然后直接做除法即可。
完整代码如下:
import pandas as pd import numpy as np # 生成原始数据 names=['Green','Blue','Red','Yellow'] values=np.random.randint(1,10,[3,4]) attributes=['Small','Small','Medium','Large'] attributes1=['Small','Medium','Large'] divisors=np.random.randint(1,5,(3,3)) db=pd.DataFrame(attributes,index=names) df=pd.DataFrame(values,columns=names) df1=pd.DataFrame(divisors,columns=attributes1) # 无循环实现除法 # 1. 将df的列名映射为对应的属性 col_to_attr = df.columns.map(db[0]) # 2. 从df1中按属性顺序取出除数,并重命名列名和df一致 aligned_divisors = df1[col_to_attr].set_axis(df.columns, axis=1) # 3. 直接执行除法 values_divided = df / aligned_divisors
为什么这个方法可行?
df.columns.map(db[0])会把每个颜色列名转换成对应的属性(比如Green→Small),这样我们就能从df1中取出和df列顺序完全匹配的除数列set_axis(df.columns, axis=1)把除数表的列名改成和df一样的颜色名称,确保两个DataFrame的行列索引完全对齐,pandas会自动按位置/索引进行元素-wise除法- 整个过程是向量式操作,比循环效率高得多,尤其是数据量较大时
验证结果一致
你可以用以下代码验证新方法和原循环方法的结果完全相同:
# 原循环方法的结果 values_divided_loop = pd.DataFrame(values, columns=names) for name in values_divided_loop.columns: values_divided_loop[name] = df[name]/df1[db[0][name]] # 对比结果 print(values_divided.equals(values_divided_loop)) # 输出True
内容的提问来源于stack exchange,提问作者gifa23
相关产品推荐
相关产品推荐

