python - Pandas:根据一列的子字符串搜索和另一列的反向创建一个新列
问题描述
我想根据一列的子字符串搜索和另一列的倒数在 Pandas 数据框中创建一个新列。这是一些数据:
import pandas as pd
import numpy as np
df = pd.DataFrame({'Manufacturer':['ABC-001', 'ABC-002', 'ABC-003', 'ABC-004', 'DEF-123', 'DEF-124', 'DEF-125', 'ABC-987', 'ABC-986', 'ABC-985'],
'Color':['04-Red', 'vs Red - 07', 'Red', 'Red--321', np.nan, np.nan, np.nan, 'Blue', 'Black', 'Orange'],
})
Manufacturer Color
0 ABC-001 04-Red
1 ABC-002 vs Red - 07
2 ABC-003 Red
3 ABC-004 Red--321
4 DEF-123 NaN
5 DEF-124 NaN
6 DEF-125 NaN
7 ABC-987 Blue
8 ABC-986 Black
9 ABC-985 Orange
我希望能够创建一个Country
基于以下逻辑命名的新列:
a) 如果Manufacturer
列包含子字符串 'ABC' 并且Color
列包含子字符串 'Red',则将 'United States' 写入Country
列
b) 如果该Manufacturer
列包含子字符串“DEF”,则将“Canada”写入该Country
列
c) 如果该Manufacturer
列包含子字符串“ABC”并且该Color
列不包含子字符串“Red”,则将“England”写入该Country
列。
我的尝试如下:
df['Country'] = np.where((df['Manufacturer'].str.contains('ABC')) & (df['Color'].str.contains('Red', na=False)), 'United States', # the 'a' case
np.where(df['Manufacturer'].str.contains('DEF', na=False), 'Canada', # the 'b' case
np.where((df['Manufacturer'].str.contains('ABC')) & (df[~df['Color'].str.contains('Red', na=False)]), 'England', # the 'c' case
'ERROR')))
但是,这会出现以下错误:
TypeError: Cannot perform 'rand_' with a dtyped [float64] array and scalar of type [bool]
错误消息表明这可能是运算符优先级的问题,如下所述:
pandas 比较引发 TypeError:无法将 dtyped [float64] 数组与 [bool] 类型的标量进行比较
Python 错误:TypeError:无法将 dtyped [float64] 数组与 [bool] 类型的标量进行比较
我相信我在这里正确地使用了括号(尽管也许我不是)。
有谁看到这个错误的原因?(或者知道更优雅的想要完成这个?)
提前致谢!
解决方案
您不想在df
此处建立索引,因此只需执行以下操作:
只是改变:(df[~df['Color'].str.contains('Red', na=False)])
至:~df['Color'].str.contains('Red', na=False)
它应该可以工作。
另外,如果您想将其分解以提高可读性并消除一些重复,我建议您这样做:
# define the parameters that define the Country variable in another table
df_countries = pd.DataFrame(
{'letters': ['ABC', 'DEF', 'ABC'],
'is_red': [True, False, False],
'Country': ['United States', 'Canada', 'England']})
# add those identifying parameters to your current table as temporary columns
df['letters'] = df.Manufacturer.str.replace('-.*', '')
df['is_red'] = df.Color.str.contains('Red', na=False)
# merge the tables together and drop the temporary key columns
df = df.merge(df_countries, how='left', on=['letters', 'is_red'])
df = df.drop(columns=['letters', 'is_red'])
或者更简洁:
in_col = lambda col, string: df[col].str.contains(string, na=False)
conds = {'United States': in_col('Manufacturer', 'ABC') & in_col('Color', 'Red'),
'Canada': in_col('Manufacturer', 'DEF'),
'England': in_col('Manufacturer', 'ABC') & ~in_col('Color', 'Red')}
df['Country'] = np.select(condlist=conds.values(), choicelist=conds.keys())
推荐阅读
- jquery - 脚本在一页而不是另一页中工作
- python - Python 类(“名称 'fetch' 未定义”)
- python - 我的“pixels[center_x + x, center_y + y] = pixel”语法有什么问题?
- spring - 在不使用基本身份验证的情况下撤销 Oauth2 令牌
- ruby - 那么,如何从我的机架应用程序中删除 Rack::ShowExceptions 呢?
- android - 如何使用 Kotlin 从 onClick 事件中获取源代码
- sql - SQL - 彼此相邻列出匹配结果
- go - path.join 上两个目录
- tableau-api - 如何使用 Tableau 将字符串中每个单词的第一个字符大写?
- python - 将元组列表打印为字符串