有时,您希望对数据的所有元素进行操作,而不是按行或按列进行分析,这被称为元素级操作。这些操作可能包括但不限于清理、标准化、缩放、编码或将数据转换为正确的形式。本文将通过不同的示例来展示如何利用DataFrame.map()
函数进行不同的数据预处理任务。
在继续之前,请注意在Pandas的早期版本中,applymap()
是对Pandas DataFrame进行元素级操作的首选方法。然而,这个方法已经被弃用并重命名为DataFrame.map()
从版本2.1.0开始。
DataFrame.map()
函数
让我们来看看它的语法[来源]:
DataFrame.map(func, na_action=None, kwargs)
语法非常简单。它只需将函数作为参数传入,并将其应用于DataFrame的每个元素。输出是与输入形状相同的转换后的DataFrame。
这里,
na_action='ignore'
,您可以跳过NaN值,而不是将它们传递给映射函数。现在我们对语法有了基本的了解,让我们继续一些使用DataFrame.map()
进行元素级操作的实际示例。
自定义函数是用户定义的函数,用于执行库中未预定义的操作。例如,如果您的DataFrame包含以华氏度为单位的每日温度,但您希望将其转换为摄氏度进行分析,您可以将DataFrame的每个元素通过转换操作。由于这种转换在Pandas中尚不可用,您需要自己定义函数。让我们来看一个示例,看看它是如何工作的。
import pandas as pd# 示例DataFrame,包含以华氏度为单位的每日温度df = pd.DataFrame({'temp_F': [85, 75, 80, 95, 90]})# 自定义函数,将温度从华氏度转换为摄氏度def convert_F_to_C(temp_F): return round((temp_F - 32) * 5/9, 2)# 使用map()函数将自定义函数应用于DataFramedf['temp_C'] = df['temp_F'].map(convert_F_to_C)# 打印最终的DataFrameprint(df)
输出:
temp_F temp_C0 85 29.441 75 23.892 80 26.673 95 35.004 90 32.22
DataFrame.map()
也可以与字典一起顺利工作。这在您希望根据某些标准将DataFrame中的数值转换为类别时特别有用。让我们举一个使用字典将学生成绩转换为字母等级的例子。
import pandas as pd# 示例DataFrame,包含数值成绩grades = {'Student': ['Qasim', 'Babar', 'Sonia'], 'Grade': [90, 85, 88]}df = pd.DataFrame(grades)# 字典,用于将数值成绩映射为字母等级grade_map = {90: 'A', 85: 'B', 88: 'B+'}# 将字典映射应用于DataFramedf['Letter_Grade'] = df['Grade'].map(grade_map)print(df)
输出:
Student Grade Letter_Grade0 Qasim 90 A1 Babar 85 B2 Sonia 88 B+
在数据预处理中,处理缺失值至关重要。这些缺失值通常表示为NaN
(非数字)。作为一名负责任的科学家,有效地处理这些缺失值是必不可少的,因为它们可能会显著影响您的分析。您可以用有意义的替代值来填充它们。例如,如果您正在计算一个班级的平均BMI,并遇到一个学生的体重可用但身高缺失的情况,您可以用同年级学生的平均身高来替代,而不是留空,从而保留数据点。
回顾一下dataframe.map()
的语法,其中包括na_action参数。这个参数允许您控制如何处理缺失值。让我通过一个例子帮助您理解这一点。
假设我们经营一家杂货店,有些价格缺失。在这种情况下,我们希望显示“不可用”而不是NaN
。您可以这样做:
import pandas as pdimport numpy as np# 示例DataFrame,包含一些价格为NaN的杂货店数据df = pd.DataFrame({ 'Product': ['Apple', 'Banana', 'Cherry', 'Date'], 'Price': [1.2, np.nan, 2.5, np.nan]})# 映射函数,用于格式化价格并处理缺失值def map_func(x): if pd.isna(x): return 'Unavailable' else: return f'${x:.2f}'# 使用默认na_action=Nonedf['Price_mapped_default'] = df['Price'].map(map_func)# 使用na_action='ignore'df['Price_mapped_ignore'] = df['Price'].map(map_func, na_action='ignore')# 打印结果DataFrameprint(df)
输出:
Product Price Price_mapped_default Price_mapped_ignore0 Apple 1.2 $1.20 $1.201 Banana NaN Unavailable NaN2 Cherry 2.5 $2.50 $2.503 Date NaN Unavailable NaN
您可以看到,当使用na_action='ignore'
时,NaN
值不会通过自定义函数,结果列中仍然是NaN
值。另一方面,当使用na_action=None
(或未指定)时,NaN
值会通过自定义函数,在这种情况下返回“不可用”。
dataframe.map()
的另一个突出特点是能够在一次调用中将多个操作链接在一起。这使您可以通过将复杂的转换分解为更小、更易管理的子部分来执行复杂的转换。这不仅使您的代码更易于理解,还使您能够简化顺序应用转换的过程。
让我们考虑一个示例,其中我们链式操作来预处理包含销售数据的数据集。假设我们想在一次转换链中格式化价格、计算税款和应用折扣:
import pandas as pd# 表示销售数据的DataFramesales_data = pd.DataFrame({ 'Product': ['Apple', 'Banana', 'Cherry'], 'Price': ["1.2", "0.8", "2.5"]})# 每个转换步骤的函数def format_price(price): return float(price)def calculate_tax(price): tax_rate = 0.1 return price * (1 + tax_rate)def apply_discount(price): discount_rate = 0.2 return price * (1 - discount_rate)# 使用dataframe.map()链式转换sales_data['Formatted_Price'] = sales_data['Price'].map(format_price).map(calculate_tax).map(apply_discount)# 打印结果DataFrameprint(sales_data)
输出:
Product Price Formatted_Price0 Apple 1.2 1.0561 Banana 0.8 0.7042 Cherry 2.5 2.200
这个dataframe.map()
函数从左到右依次执行这些转换。在这个例子中,它首先使用format_price()
将每个价格格式化为浮点数。接下来,它使用calculate_tax()
为每个格式化后的价格计算税款,最后使用apply_discount()
应用折扣。这个链式操作确保每个转换按顺序应用,基于前一个转换构建,以在Formatted_Price
列中生成所需的处理值。sales_data
DataFrame。
今天的文章到此结束!如果您有其他重要的用例或示例,您可以在其中应用dataframe.map()
函数,请随时在评论中分享。您的经验可以帮助我们一起学习和探索更多。