我有pandas的数据框(以pd导入pandas)
print(df)
C1 C2
0 0 0
1 0 0
2 1 0
3 1 1
4 1 1
5 0 1
6 0 0
7 0 0
8 0 0
9 1 0
10 1 1
11 1 1
12 0 1
13 0 0
我想在上升沿之后在“ C3”中计数+1(当C1 = 1和C2 = 0时上升沿开始) 我尝试过iterrow()
count=1
df['C3'] = 0
for index, row in df.iterrows():
if (row.C1 == 1) and (row.C2 == 0):
count += 1
df.at[index, 'C3'] = count
else:
df.at[index, 'C3'] = count
print(df)
C1 C2 C3
0 0 0 1
1 0 0 1
2 1 0 2
3 1 1 2
4 1 1 2
5 0 1 2
6 0 0 2
7 0 0 2
8 0 0 2
9 1 0 3
10 1 1 3
11 1 1 3
12 0 1 3
13 0 0 3
对于具有300000行的数据帧,它有点慢,是否有简单的方法使其变得更快?
非常感谢您的帮助!
答案 0 :(得分:2)
您可以:
counts
,它是所需条件的布尔掩码(counts
); C3
添加到值1 + counts.cumsum()
的原始df中注意:pandas根据索引值(<无>无顺序)将系列连接到数据框。进行一些破坏df或counts
系列的中间操作会产生意外的结果。
代码:
counts = (df.C1 == 1) & (df.C2 == 0)
df["C3"] = 1 + counts.cumsum()
结果:
C1 C2 C3
0 0 0 1
1 0 0 1
2 1 0 2
3 1 1 2
4 1 1 2
5 0 1 2
6 0 0 2
7 0 0 2
8 0 0 2
9 1 0 3
10 1 1 3
11 1 1 3
12 0 1 3
13 0 0 3
让我们比较以下三个选项的性能:iterrows
,df.apply
和上面的矢量化解决方案:
df = pd.DataFrame(dict(C1=np.random.choice(2,size=100000), C2=np.random.choice(2,size=100000)))
df1 = df.copy(deep=True)
df2 = df.copy(deep=True)
df3 = df.copy(deep=True)
def use_iterrows():
count=1
df1['C3'] = 0
for index, row in df1.iterrows():
if (row.C1 == 1) and (row.C2 == 0):
count += 1
df1.at[index, 'C3'] = count
else:
df1.at[index, 'C3'] = count
def use_apply():
df2['C3'] = df2.apply(lambda x: x['C1']==1 and x['C2']==0, axis=1).cumsum()+1
def use_vectorized():
counts = (df3.C1 == 1) & (df3.C2 == 0)
df3["C3"] = 1 + counts.cumsum()
%timeit use_iterrows()
# 8.23 s ± 159 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit use_apply()
# 1.54 s ± 27.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit use_vectorized()
# 1.28 ms ± 66.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
摘要:使用向量化函数是最快的(对于100k行的df,速度要快〜1000x(!))。我喜欢尽可能使用矢量化解决方案的习惯。 df.apply
的优势在于它非常灵活,可以在矢量化操作难以实现的情况下使用。我认为我从来不需要过。
答案 1 :(得分:0)
简短答案:
df['C3'] = df.apply(lambda x: x['C1']==1 and x['C2']==0, axis=1).cumsum()+1
所需结果:
C1 C2 C3
0 0 0 1
1 0 0 1
2 1 0 2
3 1 1 2
4 1 1 2
5 0 1 2
6 0 0 2
7 0 0 2
8 0 0 2
9 1 0 3
10 1 1 3
11 1 1 3
12 0 1 3
13 0 0 3
您需要记住的内容:
对于长数据,请勿使用迭代。它使速度大大降低。
应用-一种更好的替代方法,效率更高