我想从字符串长度> 4的Dataframe列中的字符串中删除前3个字符
否则它们应该保持不变。
例如
bloomberg_ticker_y
AIM9
DJEM9 # (should be M9)
FAM9
IXPM9 # (should be M9)
我可以按长度过滤字符串:
merged['bloomberg_ticker_y'].str.len() > 4
并对字符串进行切片:
merged['bloomberg_ticker_y'].str[-2:]
但是不确定如何将它们放在一起并应用于我的数据框
任何帮助将不胜感激。
答案 0 :(得分:8)
您可以使用列表理解:
df = pd.DataFrame({'bloomberg_ticker_y' : ['AIM9', 'DJEM9', 'FAM9', 'IXPM9']})
df['new'] = [x[-2:] if len(x)>4 else x for x in df['bloomberg_ticker_y']]
输出:
bloomberg_ticker_y new
0 AIM9 AIM9
1 DJEM9 M9
2 FAM9 FAM9
3 IXPM9 M9
答案 1 :(得分:7)
您可以使用numpy.where
施加条件以根据字符串长度选择切片。
np.where(df['bloomberg_ticker_y'].str.len() > 4,
df['bloomberg_ticker_y'].str[3:],
df['bloomberg_ticker_y'])
# array(['AIM9', 'M9', 'FAM9', 'M9'], dtype=object)
df['bloomberg_ticker_sliced'] = (
np.where(df['bloomberg_ticker_y'].str.len() > 4,
df['bloomberg_ticker_y'].str[3:],
df['bloomberg_ticker_y']))
df
bloomberg_ticker_y bloomberg_ticker_sliced
0 AIM9 AIM9
1 DJEM9 M9
2 FAM9 FAM9
3 IXPM9 M9
如果您喜欢基于矢量map
的解决方案,那就是
df['bloomberg_ticker_y'].map(lambda x: x[3:] if len(x) > 4 else x)
0 AIM9
1 M9
2 FAM9
3 M9
Name: bloomberg_ticker_y, dtype: object
答案 2 :(得分:5)
看到了各种各样的答案,因此决定比较它们的速度:
# Create big size test dataframe
df = pd.DataFrame({'bloomberg_ticker_y' : ['AIM9', 'DJEM9', 'FAM9', 'IXPM9']})
df = pd.concat([df]*100000)
df.shape
#Out
(400000, 1)
CS95#1 np.where
%%timeit
np.where(df['bloomberg_ticker_y'].str.len() > 4,
df['bloomberg_ticker_y'].str[3:],
df['bloomberg_ticker_y'])
结果:
163 ms ± 12.8 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
CS95#2向量化的基于map
的解决方案
%%timeit
df['bloomberg_ticker_y'].map(lambda x: x[3:] if len(x) > 4 else x)
结果:
86 ms ± 7.31 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Yatu DataFrame.mask
%%timeit
df.bloomberg_ticker_y.mask(df.bloomberg_ticker_y.str.len().gt(4),
other=df.bloomberg_ticker_y.str[-2:])
结果:
187 ms ± 18.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Vlemaistre list comprehension
%%timeit
[x[-2:] if len(x)>4 else x for x in df['bloomberg_ticker_y']]
结果:
84.8 ms ± 4.85 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
用str.replace
来regex
%%timeit
df["bloomberg_ticker_y"].str.replace(r".{3,}(?=.{2}$)", "")
结果:
324 ms ± 17.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
眼镜蛇DataFrame.apply
%%timeit
df.apply(lambda x: (x['bloomberg_ticker_y'][3:] if len(x['bloomberg_ticker_y']) > 4 else x['bloomberg_ticker_y']) , axis=1)
结果:
6.83 s ± 387 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
结论
最快的方法紧随list comprehension
之后是基于矢量map
的矢量解决方案。
最慢的方法是DataFrame.apply
(按预期),随后是str.replace
和regex
答案 3 :(得分:3)
您可以使用DataFrame.mask
:
df['bloomberg_ticker_y'] = (df.bloomberg_ticker_y.mask(
df.bloomberg_ticker_y.str.len().gt(4),
other=df.bloomberg_ticker_y.str[-2:]))
bloomberg_ticker_y
0 AIM9
1 M9
2 FAM9
3 M9
答案 4 :(得分:3)
您也可以使用DataFrame.apply:
Trim()
输出:
List<string> centerIds_list = "1LE, 1GE".Split(',').Select(x => x.Trim()).ToList();
答案 5 :(得分:2)
另一种方法是使用正则表达式:
df["bloomberg_ticker_y"].str.replace(r".{3,}(?=.{2}$)", "")
#0 AIM9
#1 M9
#2 FAM9
#3 M9
该模式的意思是:
.{3,}
:匹配3个或更多字符(?=.{2}$)
:积极地期待正好2个字符,然后是字符串的结尾。