为啥代码运行如此缓慢,以至于我在其中使用了 for 循环。有更快的方法吗?
Posted
技术标签:
【中文标题】为啥代码运行如此缓慢,以至于我在其中使用了 for 循环。有更快的方法吗?【英文标题】:Why is the code running so slow that I use for loop in it. Is there a faster way?为什么代码运行如此缓慢,以至于我在其中使用了 for 循环。有更快的方法吗? 【发布时间】:2021-08-09 22:14:37 【问题描述】:我有这样的数据。
data = [
['2019-01-01', 'a',0],
['2019-01-02', 'b',0],
['2019-01-03', 'c',0],
['2019-01-04', 'd',0],
['2019-01-05', 'a',0],
['2019-01-05', 'd',0],
['2019-01-06', 'd',0],
['2019-01-07', 'f',0],
['2019-01-08', 'c',0],
['2019-01-08', 'b',0],
['2019-01-08', 'g',0],
['2019-01-08', 'h',0],
['2019-01-09', 'q',0],
['2019-01-09', 'b',0],
['2019-01-09', 'y',0],
['2019-01-10', 'd',0],
['2019-01-11', 'z',0],
['2019-01-11', 'x',0],
['2019-01-11', 'c',0],
['2019-01-12', 'y',0],
['2019-01-13', 'x',0],
['2019-01-13', 'q',0],
['2019-01-14', 't',0],
['2019-01-15', 'i',0]]
df = pd.DataFrame(data, columns = ['Date', 'Column1','Column2'])
Date Column1 Column2
0 2019-01-01 a 0
1 2019-01-02 b 0
2 2019-01-03 c 0
3 2019-01-04 d 0
4 2019-01-05 a 0
5 2019-01-05 d 0
6 2019-01-06 d 0
7 2019-01-07 f 0
8 2019-01-08 c 0
9 2019-01-08 b 0
10 2019-01-08 g 0
11 2019-01-08 h 0
12 2019-01-09 q 0
13 2019-01-09 b 0
14 2019-01-09 y 0
15 2019-01-10 d 0
16 2019-01-11 z 0
17 2019-01-11 x 0
18 2019-01-11 c 0
19 2019-01-12 y 0
20 2019-01-13 x 0
21 2019-01-13 q 0
22 2019-01-14 t 0
23 2019-01-15 i 0
我的目标是查看每个 column1 元素,如果该元素之前存在于 column1 中,则将 column2 的值设为 1。
我写了这样的代码。
for i in range(0,len(df)):
for j in range(0,i-1):
if df.Column1[i] == df.Column1[j]:
df.Column2[i] = 1
我得到了我想要的结果。
Date Column1 Column2
0 2019-01-01 a 0
1 2019-01-02 b 0
2 2019-01-03 c 0
3 2019-01-04 d 0
4 2019-01-05 a 1
5 2019-01-05 d 1
6 2019-01-06 d 1
7 2019-01-07 f 0
8 2019-01-08 c 1
9 2019-01-08 b 1
10 2019-01-08 g 0
11 2019-01-08 h 0
12 2019-01-09 q 0
13 2019-01-09 b 1
14 2019-01-09 y 0
15 2019-01-10 d 1
16 2019-01-11 z 0
17 2019-01-11 x 0
18 2019-01-11 c 1
19 2019-01-12 y 1
20 2019-01-13 x 1
21 2019-01-13 q 1
22 2019-01-14 t 0
23 2019-01-15 i 0
但是当我在 100000 行数据上运行这段代码时,它运行得非常慢。
有没有办法在更短的时间内做到这一点,或者对于这个问题有不同的解决方案建议?
感谢解答
【问题讨论】:
你是指column2还是column3的值?您的代码有第 2 列... 【参考方案1】:你可以在column1上做groupby和cumcount,然后clip上限为1:
df['Column2'] = df.groupby("Column1").cumcount().clip(upper=1)
但是,更简洁的方法是在此处检查 series.duplicated
:
df['Column2'] = df['Column1'].duplicated().astype(int)
print(df)
Date Column1 Column2
0 2019-01-01 a 0
1 2019-01-02 b 0
2 2019-01-03 c 0
3 2019-01-04 d 0
4 2019-01-05 a 1
5 2019-01-05 d 1
6 2019-01-06 d 1
7 2019-01-07 f 0
8 2019-01-08 c 1
9 2019-01-08 b 1
10 2019-01-08 g 0
11 2019-01-08 h 0
12 2019-01-09 q 0
13 2019-01-09 b 1
14 2019-01-09 y 0
15 2019-01-10 d 1
16 2019-01-11 z 0
17 2019-01-11 x 0
18 2019-01-11 c 1
19 2019-01-12 y 1
20 2019-01-13 x 1
21 2019-01-13 q 1
22 2019-01-14 t 0
23 2019-01-15 i 0
【讨论】:
我必须更频繁地使用这个.clip
。它比.gt()
干净,然后转换为int。 +1【参考方案2】:
您可以在 Column1
上使用 .groupby
和“cumcount”转换:
df["Column2"] = (
df.groupby("Column1", sort=False)["Column1"]
.transform("cumcount")
.gt(0)
.astype(int)
)
print(df)
打印:
Date Column1 Column2
0 2019-01-01 a 0
1 2019-01-02 b 0
2 2019-01-03 c 0
3 2019-01-04 d 0
4 2019-01-05 a 1
5 2019-01-05 d 1
6 2019-01-06 d 1
7 2019-01-07 f 0
8 2019-01-08 c 1
9 2019-01-08 b 1
10 2019-01-08 g 0
11 2019-01-08 h 0
12 2019-01-09 q 0
13 2019-01-09 b 1
14 2019-01-09 y 0
15 2019-01-10 d 1
16 2019-01-11 z 0
17 2019-01-11 x 0
18 2019-01-11 c 1
19 2019-01-12 y 1
20 2019-01-13 x 1
21 2019-01-13 q 1
22 2019-01-14 t 0
23 2019-01-15 i 0
【讨论】:
【参考方案3】:使用pandas
函数的其他答案可能要快得多,但这里有一个类似于您原来的解决方案,它消除了双重迭代。
exists = dict()
for i in range(len(df)):
df.Column2[i] = exists.get(df.Column1[i], 0)
if not df.Column2[i]:
exists[df.Column1[i]] = 1
print(df)
【讨论】:
以上是关于为啥代码运行如此缓慢,以至于我在其中使用了 for 循环。有更快的方法吗?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我使用多处理/多线程的函数在 for 循环中使用时如此缓慢,但在循环之外却没有?
与 ObjectContext 相比,为啥在 EF 4.1 中插入实体如此缓慢?
为啥我的 Apps 脚本删除循环运行如此缓慢?我可以提高性能吗?