我有一个包含许多列的数据框,其中任意数目的列名称适合特定的字符串模式。我想创建一个新列,如果其他任何列中有一个“ r”,则将其设置为“ r”。我可以做这样的事情:
for col in df.columns:
if 'abc' in col:
for i in df.index:
if df.ix[i, col] == 'r':
df.ix[i, 'newcol'] = 'r'
但是,这有点丑陋且缓慢。有更快的方法吗?
编辑:包括我的源数据可能看起来像的示例:
df = pd.DataFrame({'abc1':['r','r','n','n'], 'abc2':['r','n','n','r'], 'xyz1':['r','n','n','n'], 'xyz2':['n','n','r','n']})
我需要的输出(在'newcol'中)是:
abc1 abc2 xyz1 xyz2 newcol
0 r r r n r
1 r n n n r
2 n n n r nan
3 n r n n r
(只要不是'r',nan几乎可以用任何东西代替)。
另外,newcol可以包含
True, True, False, True
,对于我的目的也可以正常工作。 最佳答案
好吧,我可能会这样做(一个示例数据框有望很好地捕获您的情况):
>>> df
A B abc1 abc2 abc3 abc4
0 1 4 x r a d
1 1 3 y d b e
2 2 4 z e c r
3 3 5 r g d f
4 4 8 z z z z
获取感兴趣的列:
>>> cols = [x for x in df.columns if 'abc' in x]
>>> cols
['abc1', 'abc2', 'abc3', 'abc4']
>>> df['newcol'] = (df[cols] == 'r').any(axis=1).map({True:'r',False:'np.nan'})
>>> df
A B abc1 abc2 abc3 abc4 newcol
0 1 4 x r a d r
1 1 3 y d b e np.nan
2 2 4 z e c r r
3 3 5 r g d f r
4 4 8 z z z z np.nan
这应该很快。我认为即使在这里使用map也会被Cythonized调用。如果一个布尔向量足以用于newcol,则可以将其简化为以下形式:
>>> df['newcol'] = (df[cols] == 'r').any(axis=1)
>>> df
A B abc1 abc2 abc3 abc4 newcol
0 1 4 x r a d True
1 1 3 y d b e False
2 2 4 z e c r True
3 3 5 r g d f True
4 4 8 z z z z False
现在,如果需要检查字符串是否包含“ r”而不是等于“ r”,则可以执行以下操作:
>>> df
A B abc1 abc2 abc3 abc4
0 1 4 x root a d
1 1 3 y d b e
2 2 4 z e c bar
3 3 5 r g d f
4 4 8 z z z z
>>> cols = [x for x in df.columns if 'abc' in x]
>>> df['newcol'] = df[cols].apply(lambda x: x.str.contains('r'),axis=0).any(axis=1)
>>> df['newcol'] = df['newcol'].map({True:'r',False:'np.nan'})
>>> df
A B abc1 abc2 abc3 abc4 newcol
0 1 4 x root a d r
1 1 3 y d b e np.nan
2 2 4 z e c bar r
3 3 5 r g d f r
4 4 8 z z z z np.nan
这应该仍然非常快,因为它对每个列使用
pandas
向量化的字符串方法(应用是跨列的,而不是行的迭代)。