python - 如果条件不满足,为什么带有条件的 np.where 不能仅处理数据框中的一行
问题描述
这是一个例子:
cars2 = {'Brand': ['Hon*da\nCivic', 'BM*AMT*B6*W'],'Price': [22000, 55000]}
df2 = pd.DataFrame(cars2, columns = ['Brand', 'Price'])
df2['Allowed_Amount'] = np.where(
df2['Brand'].apply(lambda x: x.count("AMT" + "*" + "B6") > 0),
df2['Brand'].str.split("AMT" + "*").str[1].str.split("B6").str[1].str[1:].str.split('\n').str[0], 0.00)
输出:
Brand Price Allowed_Amount
0 Hon*da\nCivic 22000 0
1 BM*AMT*B6*W 55000 W
这正是我需要的。
但是,如果 df 仅包含不满足条件的一行,则会出现错误:
cars = {'Brand': ['Hon*da\nCivic'],'Price': [22000]}
df = pd.DataFrame(cars, columns = ['Brand', 'Price'])
df['Allowed_Amount'] = np.where(
df['Brand'].apply(lambda x: x.count("AMT" + "*" + "B6") > 0),
df['Brand'].str.split("AMT" + "*").str[1].str.split("B6").str[1].str[1:].str.split('\n').str[0], 0.00)
输出:
AttributeError: Can only use .str accessor with string values!
我需要的:
Brand Price Allowed_Amount
0 Hon*da\nCivic 22000 0
为什么不满足条件不退出?如何使此代码也适用于一行?
解决方案
您的代码的问题是df['Brand'].str.split("AMT" + " ")* 在“负”情况下返回大小为1的列表(单个元素中的整个源字符串 )。
在这种情况下.str[1](按照前面的代码)返回None并且您的代码中的“以下”方法不能在它上面调用。
但是在Pandas中,只有在每个源元素都发生上述情况时才会引发实际异常,就像df的情况一样。
我还认为这么长的str.split、str和 index 选择序列很难阅读。
尝试另一种基于使用正则表达式提取的方法:
df['Allowed_Amount'] = df['Brand'].str.extract(r'AMT\*.*?B6.(.*)').fillna(0)
正则表达式的详细信息:
AMT\*
- 匹配AMT
和星号。.*?
- 尽可能少地匹配任意数量的字符(“AMT*”和“B6”之间的字符,如果有的话)。也许你可以从正则表达式中删除这个片段。B6
- 代表自己。.
- 匹配任何单个字符([1:]
代码中的对应字符)。(.*)
- 将文本匹配到换行符(不包括,因为点与换行符不匹配)或字符串的末尾,作为捕获组,所以这只是提取的内容。
如果上述正则表达式不匹配,则为该行返回NaN 。
然后这些NaN值被替换为0,因为之后调用了fillna(0) 。
在df2上尝试相同的操作。
因此,通过这种方式,您将使用更短且更具可读性的代码来实现您想要的结果。
当然,它需要一些正则表达式的知识,但绝对值得花一些时间来学习它们。
按照问题编辑
要使用给定的分隔符替换正则表达式中的文字星号,您可以定义以下函数,为新列生成内容:
def myExtract(df, delimiter='*'):
pat = rf'AMT\{delimiter}B6.(.*)'
return df['Brand'].str.extract(pat).fillna(0)
如你看到的:
- 使用f-string功能将分隔符合并到正则表达式中(可以与r-string 共存),
- 它必须以反斜杠开头,以按字面意思对待它 (而不是特殊的正则表达式字符)。
要生成新的列,只需调用此函数,至少传递源 DataFrame(以及可选的右分隔符):
df['Allowed_Amount'] = myExtract(df); df
df2也是如此。
推荐阅读
- loops - 我将如何将方法中的整数更改为字符串?
- react-native - TypeError:试图分配给只读属性。在 Expo / GraphQL Apollo 客户端上
- authentication - 使用 SSO 对网络驱动器的用户进行身份验证
- c# - 如何获取云端分发IP?
- php - 使用 Guzzle 下载文件
- javascript - 如何在 Google Drive 的特定文件夹上使用 React Native 上传文档?
- scala - 如何在 Scala 中动态类型转换一个值?
- listview - ListView 小部件未在我的屏幕上显示并且无法正常工作(在 Flutter 中)
- javascript - 无法理解 requireJS 的 require() 函数
- python - AttributeError:模块“tensorflow_docs”没有属性“plots”