用值填充非常大的数据帧的快速方法

2024-10-03 11:21:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个非常大的数据帧,它有100年的日期作为列标题(即大约36500列),100年的日期作为索引(即大约36500行)。我有一个函数,它计算数据帧的每个元素的值,需要运行36500^2次。在

好的,问题不在于函数的快速性,而在于给数据帧赋值。即使我用这种方式分配一个常数,每6个赋值也需要1秒的时间。很明显,你可以看出我很胖:

for i, row in df_mBase.iterrows():
    for idx, val in enumerate(row):
        df_mBase.ix[i][idx] = 1
    print(i)

通常在C/Java中,我只需通过一个36500x36500的双循环进行循环,并通过索引直接访问预先分配的内存,这可以在恒定的时间内实现,几乎没有任何开销。但在python中这似乎不是一个选项?在

在数据帧中存储这些数据的最快方法是什么?不管是不是Python,我只追求速度-我不喜欢优雅。在


Tags: 数据函数in元素标题dffor方式
2条回答

您应该使用原生python或numpy创建数据结构,并将数据传递给DataFrame构造函数。如果您的函数可以使用numpy的函数/操作编写,那么您可以使用numpy的向量化特性来避免在所有索引上循环。在

下面是一个使用合成函数的示例:

import numpy as np
import pandas as pd
import datetime as dt
import dateutil as du

dates = [dt.date(2017, 1, 1) - du.relativedelta.relativedelta(days=i) for i in range(36500)]
data = np.zeros((36500,36500), dtype=np.uint8)

def my_func(i, j):
    return (sum(divmod(i,j)) - sum(divmod(j,i))) % 255

for i in range(1, 36500):
    for j in range(1, 36500):
        data[i,j] = my_func(i,j)

df = pd.DataFrame(data, columns=dates, index=dates)

df.head(5)
#returns:

            2017-08-21  2017-08-20  2017-08-19  2017-08-18  2017-08-17  \
2017-08-21           0           0           0           0           0
2017-08-20           0           0         254         253         252
2017-08-19           0           1           0           0           0
2017-08-18           0           2           0           0           1
2017-08-17           0           3           0         254           0

               ...      1917-09-19  1917-09-18  1917-09-17  1917-09-16
2017-08-21     ...               0           0           0           0
2017-08-20     ...             225         224         223         222
2017-08-19     ...             114         113         113         112
2017-08-18     ...              77          76          77          76
2017-08-17     ...              60          59          58          57

有几个原因可以解释为什么这可能会变慢

.九

{{label{1}和cdr}都是基于索引的{1},但对于cd1}和cd1}都是严格的索引。 我假设.ix在幕后做了很多魔术,以确定是否需要标签或基于位置的索引

.I错误

返回一个(新的?)Series表示每行。基于列的迭代可能更快,比如.iteritems在列上迭代

【】【】

df_mBase.ix[i][idx]返回一个Series,然后从中获取元素idx,该元素的值为1。在

df_mBase.loc[i, idx] = 1

应该改善一下

标杆管理

^{pr2}$
                              0.03        0.1         0.3         1.0         3.0
assign_applymap               0.001989    0.009862    0.018018    0.105569    0.549511
assign_vectorized             0.002974    0.008428    0.035994    0.162565    3.810138
assign_index                  0.013717    0.137134    1.288852    14.190128   111.102662
assign_column2                0.026260    0.186588    1.664345    19.204453   143.103077
assign_column                 0.016811    0.212158    1.838733    21.053627   153.827845
assign_itertuples             0.025130    0.249886    2.125968    24.639593   185.975111
assign_iloc_product_range     0.026982    0.247069    2.199019    23.902244   186.548500
assign_iloc_product           0.021225    0.233454    2.437183    25.143673   218.849143
assign_loc_product            0.018743    0.290104    2.515379    32.778794   258.244436
assign_loc                    0.029050    0.349551    2.822797    32.087433   294.052933
assign_original               0.034315    0.337207    2.714154    30.361072   332.327008

结论

timing plot

如果可以使用矢量化,请这样做。根据计算结果,可以使用其他方法。如果您只需要使用的值,applymap似乎最快。如果还需要索引和或列,请使用列

如果不能向量化,df[column][index] = x的工作速度最快,以df.iteritems()作为一个接近的秒迭代列

相关问题 更多 >