
在数据处理和分析中,我们经常需要根据现有列的复杂逻辑来生成或更新新的数据列。这其中一个常见的场景是,从包含特定模式的字符串列中提取数值,并依据这些数值的特征(如大小范围或数字位数)来赋予新列不同的分类标签。传统的方法可能涉及循环遍历行,但这在处理大型数据集时效率低下。pandas提供了强大的向量化操作,能够以更高效、简洁的方式完成此类任务。本文将以一个具体示例,详细讲解如何利用pandas的str.extract、pd.cut和np.log10等函数,实现基于复杂条件的列值更新。
假设我们有一个Pandas DataFrame,其中包含Server和Port两列。Port列的值通常以“Ethernet”开头,后跟一个或多个数字,例如Ethernet3、Ethernet12、Ethernet567。我们的目标是根据Port列中“Ethernet”后的数字特征,创建一个名为function_val的新列。具体的分类规则如下:
原始数据框示例如下:
import pandas as pd
import numpy as np
data = {
'Server': ['Ser123', 'Ser123', 'Ser123', 'Ser123', 'Serabc', 'Serabc', 'Serabc', 'Serabc'],
'Port': ['Ethernet3', 'Ethernet4', 'Ethernet12', 'Ethernet567', 'Ethernet2', 'Ethernet34', 'Ethernet458', 'Ethernet5689']
}
df = pd.DataFrame(data)
print("原始DataFrame:")
print(df)期望的输出数据框:
Server Port function_val 0 Ser123 Ethernet3 5k 1 Ser123 Ethernet4 5k 2 Ser123 Ethernet12 10k 3 Ser123 Ethernet567 20k 4 Serabc Ethernet2 5k 5 Serabc Ethernet34 10k 6 Serabc Ethernet458 20k 7 Serabc Ethernet5689 20k
这种方法适用于根据提取出的数值在不同区间内进行分类赋值的场景。它首先通过正则表达式从字符串中提取数字,然后使用pd.cut函数将这些数字分箱并分配相应的标签。
首先,我们需要从Port列的字符串中提取出末尾的数字。这可以通过Pandas的字符串方法str.extract()结合正则表达式实现。正则表达式r'(\d+)$'用于匹配字符串末尾的一个或多个数字。expand=False参数确保结果是一个Series而不是DataFrame。提取出的数字字符串随后需要转换为整数类型,以便进行数值比较和分箱。
# 提取Port列中的数字并转换为整数
extracted_numbers = df['Port'].str.extract(r'(\d+)$', expand=False).astype(int)
print("\n提取出的数字:")
print(extracted_numbers)接下来,我们定义数值区间(bins)和对应的标签(labels)。pd.cut()函数会将extracted_numbers中的每个值放入其所属的区间,并赋予相应的标签。
# 定义分箱的边界和标签
bins = [0, 10, 100, np.inf]
labels = ['5k', '10k', '20k']
# 使用pd.cut进行分箱并创建新列
df['function_val'] = pd.cut(extracted_numbers, bins=bins, labels=labels, right=True)
print("\n使用pd.cut后的DataFrame:")
print(df)代码解析:
如果分类逻辑是严格基于数字的位数(例如,1位数、2位数、3位数),我们可以采用另一种方法:先提取数字,然后计算其位数,最后将位数映射到相应的标签。
同样,我们首先提取数字并转换为整数。接着,利用数学函数np.log10()和np.ceil()来计算数字的位数。
# 提取数字并计算位数
num_digits = np.ceil(np.log10(df['Port'].str.extract(r'(\d+)$', expand=False).astype(int) + 1)).astype(int)
print("\n提取出的数字位数:")
print(num_digits)计算出每个数字的位数后,我们创建一个字典来定义位数与目标值之间的映射关系,然后使用Series的map()方法将位数转换为对应的function_val。
# 定义位数到标签的映射
labels_by_digits = {1: '5k', 2: '10k', 3: '20k', 4: '20k'} # 根据原始需求,4位数也应为'20k'
# 使用map进行赋值
df['function_val_by_digits'] = num_digits.map(labels_by_digits)
print("\n使用np.log10和map后的DataFrame:")
print(df)注意事项: 如果labels_by_digits字典中没有对应的位数,map()方法将默认填充NaN。你可以通过在字典中添加一个默认值或使用fillna()来处理这些情况。例如,如果希望所有超过3位数的都显示为“other”,可以设置labels_by_digits = {1: '5k', 2: '10k', 3: '20k', 4: 'other'}。在我们的例子中,为了满足原始需求,4位数也映射到'20k'。
本文介绍了两种在Pandas数据框中根据复杂条件更新列值的有效方法:
这两种方法都利用了Pandas的向量化操作,避免了低效的行级循环,从而在处理大规模数据集时表现出卓越的性能。在实际应用中,选择哪种方法取决于你的具体分类需求:是基于数值的绝对范围,还是基于数字的位数。理解并熟练运用这些技术,将大大提高你在Pandas中数据清洗和特征工程的效率。
以上就是Pandas数据框中基于复杂条件更新列值:高效提取、分类与赋值实践的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号