首页 > 解决方案 > 根据另一个数据框值应用映射函数

问题描述

一般问题:我有两个相似的数据框(相同的形状,相同的变量但不同的值)。
如何applymap根据 df2 中相同单元格的值对 df1 的每个单元格执行函数。

我的具体问题:如何applymap(round())根据 df2 中该单元格的十进制数在 df1 的每个单元格上运行。

我通过跨数据框列的 for 循环来做到这一点。我现在想使用df.applymap()ordf.apply(np.vectorized())函数优化代码以避免循环。

可选:我还想通过变量来洗牌这个十进制数字。

下面的代码可以正常工作,但需要优化。

import numpy as np
import pandas as pd 
   
# Count decimal number
def decimal_count(number):
   f = str(number)
   if '.' in f:
       digits = f[::-1].find('.')
   else : digits = 0
   return digits 
   
# dataframe I want to round
df_to_round = pd.DataFrame({'Integers' :[1, 2.3, 4.1, 4, 5], 
                  'Float' :[1.1, 2.2, 3.5444, 4.433 ,5.5555]})

# dataframe with correct decimal number
df_rounded = pd.DataFrame({'Integers' :[1, 2, 3, 4, 5], 
                  'Float' :[1.1, 6.233, 3.34, 4.46 ,5.777]})


# round to the right decimal
for column in inverse_quanti.columns:

   # get decimal 
   df_to_round['decimals'] = df_rounded[column].apply(decimal_count)

   # shuffle decimal level 
   # only if needed
   # df_to_round['decimals'] = np.random.permutation(df_to_round['decimals'].values)

   # Apply round function to df_to_round
   df_to_round[column] = df_to_round[[column, 'decimals']].apply(lambda x : round(x[column], int(x['decimals'])), axis= 1)

   df_to_round.drop(['decimals'], axis = 1, inplace = True)

我的主要障碍是如何使# Apply round function to df_to_round步骤适应矢量化方法。

标签: pythonpandasdataframevectorizationpython-applymap

解决方案


我通常为此使用swifter,因为它是apply()在 pandas 中对函数进行矢量化的最简单的选择。

安装它:

$ pip install -U pandas # upgrade pandas
$ pip install swifter # first time installation
$ pip install swifter[modin-ray] # first time installation including modin[ray]
$ pip install swifter[modin-dask] # first time installation including modin[dask]

$ pip install -U swifter # upgrade to latest version if already installed

然后在代码中像这样使用它。

注意groupby():在 .之前使用 a 时不起作用apply()

import swifter

# round to the right decimal
for column in inverse_quanti.columns:

   # get decimal 
   df_to_round['decimals'] = df_rounded[column].swifter.apply(decimal_count)

   # shuffle decimal level 
   # only if needed
   # df_to_round['decimals'] = np.random.permutation(df_to_round['decimals'].values)

   # Apply round function to df_to_round
   df_to_round[column] = df_to_round[[column, 'decimals']].swifter.apply(lambda x : round(x[column], int(x['decimals'])), axis= 1)

   df_to_round.drop(['decimals'], axis = 1, inplace = True)

推荐阅读