应用和嵌套循环的区别

3
我正在尝试在Python中构建一个数据框,其中填充了1和0,取决于一列中的数字:
Date        Hour
2005-01-01  1
2005-01-01  2
2005-01-01  3
2005-01-01  4

我想根据“小时”中的数字创建新列,并在每一列中填充1,如果该行等于“小时”中的值,则填充0。

Date        Hour HE1 HE2 HE3 HE4
2005-01-01  1    1   0   0   0
2005-01-01  2    0   1   0   0
2005-01-01  3    0   0   1   0
2005-01-01  4    0   0   0   1

我可以用这段代码实现,但需要很长时间:

for x in range(1,5):
    _HE = 'HE' + str(x)
    for i in load.index:
        load.at[i, _HE] = 1 if load.at[i,'Hour']==x else 0

我觉得这是使用 .apply() 来加速的一个绝佳应用(不是说笑),但我无法使它正常工作。

你如何来提高其运行速度?


当然,嵌套的for循环并不是首选。 - U13-Forward
1
.apply通常不比for循环更快。.apply在Python解释器层面上是一个for循环 - juanpa.arrivillaga
3个回答

5

在pandas中,不推荐使用循环,因为如果存在某些向量化的解决方案,则速度会变慢。

注意:在函数apply中也有循环。

因此,请使用pandas.get_dummiesDataFrame.add_prefix以及join来添加到原始的df

df = df.join(pd.get_dummies(df['Hour'].astype(str)).add_prefix('HE'))
print (df)
         Date  Hour  HE1  HE2  HE3  HE4
0  2005-01-01     1    1    0    0    0
1  2005-01-01     2    0    1    0    0
2  2005-01-01     3    0    0    1    0
3  2005-01-01     4    0    0    0    1

相似的函数具有不同的性能:

df = pd.concat([df] * 1000, ignore_index=True)

In [62]: %timeit df.join(pd.get_dummies(df['Hour'].astype(str)).add_prefix('HE'))
3.54 ms ± 277 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

#U9-Forward solution
In [63]: %timeit df.join(df['Hour'].astype(str).str.get_dummies().add_prefix('HE'))
61.6 ms ± 297 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

3

pandas.factorize and array slice assignment

j, h = pd.factorize(df.Hour)
i = np.arange(len(df))

b = np.zeros((len(df), len(h)), dtype=h.dtype)
b[i, j] = 1

df.join(pd.DataFrame(b, df.index, h).add_prefix('HE'))

         Date  Hour  HE1  HE2  HE3  HE4
0  2005-01-01     1    1    0    0    0
1  2005-01-01     2    0    1    0    0
2  2005-01-01     3    0    0    1    0
3  2005-01-01     4    0    0    0    1

0
尽管与@jezrael的答案非常相似,但这个答案更好,它只是使用.str访问器来进行get_dummies
print(df.join(df['Hour'].astype(str).str.get_dummies().add_prefix('HE')))

输出:

         Date  Hour  HE1  HE2  HE3  HE4
0  2005-01-01     1    1    0    0    0
1  2005-01-01     2    0    1    0    0
2  2005-01-01     3    0    0    1    0
3  2005-01-01     4    0    0    0    1

2
那绝对同意 ;) 但比 pd.get_dummies - jezrael
1
@jezrael 这是真的,但至少比他好一点。 - U13-Forward
1
循环和apply是等价的。顺便说一下,我没有投反对票。 - juanpa.arrivillaga
1
@U9-前行 - 不,我没有踩反对。请检查上面的截图。如果踩了反对,它会变成橙色。 - jezrael
1
我给你的回答点了踩。如果你的回答对jez有所帮助,我可以理解你的复制粘贴,但在这种情况下(以及大多数情况下),使用字符串访问器是严格劣于其他方法的,因此我认为这个答案没有用处。但由于它确实得到了期望的输出,我已经将其删除。 - user3483203
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接