pandas:查找部分字符串并在新列中使用它
Posted
技术标签:
【中文标题】pandas:查找部分字符串并在新列中使用它【英文标题】:pandas: find partial string and use it in new columns 【发布时间】:2016-09-27 00:54:44 【问题描述】:如果某个字符串是另一个列的子字符串,我想创建一个新列。假设我有一个包含一列 df['A'] 的 DataFrame:
A
0 bbh AA chd
1 d10 DKL BB
2 kj AAdbl 5
3 kBB d7d dl
还有一个清单:
check = ['AA', 'BB']
现在我想创建列 df['B'],如果它们在 df['A'] 中找到,它会接管列表中的值:
A B
0 bbh AA chd AA
1 d10 DKL BB BB
2 kj AAdbl 5 AA
3 kBB d7d dl BB
如何在循环遍历列表(实际上它不仅仅是两个项目)或应用函数时完成此任务?
【问题讨论】:
在 pandas 中执行此操作的首选方法是df['A'].str.extract('(%s)' % '|'.join(check), expand=False)
。正则表达式捕获组(AA|BB)
用于在此处提取值。如果您想在同一个单元格中查找多个字符串,还可以查看 extractall
和 findall
。
【参考方案1】:
设置
import pandas as pd
text = """A
bbh AA chd
d10 DKL BB
kj AAdbl 5
kBB d7d dl"""
df = pd.read_csv(StringIO(text))
check = ['AA', 'BB']
print df
A
0 bbh AA chd
1 d10 DKL BB
2 kj AAdbl 5
3 kBB d7d dl
解决方案
df_expanded = df.A.str.split(expand=True)
checked = pd.concat(
[df_expanded.apply(lambda s: s.str.rfind(chk)) for chk in check],
keys=check
)
where = (checked >= 0).any(axis=1).unstack(0)
where = where.mul(where.columns.to_series(), axis=1)
final = pd.Series()
where.replace('', np.nan, inplace=True)
for c in where.columns:
final = final.combine_first(where.loc[:, c])
df['B'] = final
print df
A B
0 bbh AA chd AA
1 d10 DKL BB BB
2 kj AAdbl 5 AA
3 kBB d7d dl BB
【讨论】:
谢谢 piRSquared,但您的解决方案在索引 2 和 3 中提供“无”,而 AA 和 BB 组合应作为子字符串找到。 @AI_Iskander 已修复【参考方案2】:尝试使用iterrows 遍历行并检查行是否包含检查列表中的任何元素,然后将其放入新列中。
for idx, row in df.iterrows():
for c in check:
if c in row['A']:
df.ix[idx, 'B'] = c
输出:
df
Out[16]:
A B
0 bbh AA chd AA
1 d10 DKL BB BB
2 kj AAdbl 5 AA
3 kBB d7d dl BB
有点困惑:如果 df 同时包含 AA
和 BB
怎么办?在这种情况下,我的代码可能需要根据您希望如何定义输出行为进行一些修改。
【讨论】:
谢谢@曲东。它按预期工作。我刚收到这条消息(尽管我认为我可以丢弃它):'SettingWithCopyWarning:试图在 DataFrame 中的切片副本上设置一个值。尝试使用 .loc[row_indexer,col_indexer] = value 代替 '. 虽然这行得通,但使用iterrows
确实应该被视为 pandas 的最后手段,因为它非常很慢。在可能的情况下,最好坚持使用str.extract
等矢量化字符串方法来处理此类任务。
感谢@ajcr,作品和矢量化甚至是首选。不过,仍然需要更好地理解该语法。以上是关于pandas:查找部分字符串并在新列中使用它的主要内容,如果未能解决你的问题,请参考以下文章
Pandas - 使用 PostCoder 在每一行中查找纬度和经度,然后在新列中返回 Postcode