提高数据集生成的代码效率



我正在尝试生成一个数据集,其中给定年份范围内的每一天都有固定数量的商店。反过来,每家商店销售固定数量的产品。特定于每个商店和日期的产品具有销售额值 (£( 和销售的产品数量。

但是,运行这些 for 循环需要一段时间来创建数据集。

无论如何我可以提高代码的效率吗?

# Generate one row Dataframes (for concatenation) for each product, in each store, on each date
dataframes = []
for d in datelist:
for s in store_IDs:
for p in product_IDs:
products_sold = random.randint(1,101)
sales = random.randint(100,1001)
data_dict = {'Date': [d], 'Store ID': [s], 'Product ID': [p], 'Sales': [sales], 'Number of Products Sold': [products_sold]}
dataframe = pd.DataFrame(data_dict) 
dataframes.append(dataframe)
test_dataframe = pd.concat(dataframes)

你的代码现在非常慢的主要原因是你把数据帧构造埋在三重循环中。 这不是必需的。 现在,您正在每个循环内创建一个新的数据帧。 以某种类型的格式创建所有数据的效率要高得多,pandas可以引入,然后创建一次数据帧。

对于您拥有的结构,您可以做的最简单的 mod 是制作数据行列表,像现在构建的那样为每一行在该列表中附加一个新字典,然后从字典列表中创建一个 df... 熊猫知道如何做到这一点。 我还删除了字典中项目的列表括号。 那没有必要。

import pandas as pd
import random
datelist = [1, 2, 4, 55]
store_IDs = ['6A', '27B', '12C']
product_IDs = ['soap', 'gum']

data = []  # I just renamed this for clarity
for d in datelist:
for s in store_IDs:
for p in product_IDs:
products_sold = random.randint(1,101)
sales = random.randint(100,1001)
data_dict = {'Date': d, 'Store ID': s, 'Product ID': p, 'Sales': sales, 'Number of Products Sold': products_sold}
data.append(data_dict)  # this is building a list of dictionaries...
print(data[:3])
df = pd.DataFrame(data)
print(df.head())

收益 率:

[{'Date': 1, 'Store ID': '6A', 'Product ID': 'soap', 'Sales': 310, 'Number of Products Sold': 35}, {'Date': 1, 'Store ID': '6A', 'Product ID': 'gum', 'Sales': 149, 'Number of Products Sold': 34}, {'Date': 1, 'Store ID': '27B', 'Product ID': 'soap', 'Sales': 332, 'Number of Products Sold': 60}]
Date Store ID Product ID  Sales  Number of Products Sold
0     1       6A       soap    310                       35
1     1       6A        gum    149                       34
2     1      27B       soap    332                       60
3     1      27B        gum    698                       21
4     1      12C       soap    658                       51
[Finished in 0.6s]

你意识到你的尺寸很大吗?

大小约为 3 年半(以天为单位(= 1277 乘以 乘以 99 个商店 = 126,423 乘以 8999 个产品 = 1,137,680,577 行。

如果您需要平均 16 个字节(这已经不多了(,您至少需要 17GB 的内存!

出于这个原因,Store_IDsProduct_IDs实际上应该只是小整数,就像更具描述性名称的表中的索引一样。

提高效率的方法是减少函数调用! 例如,您可以使用numpy随机数生成来批量生成随机值。

假设所有涉及的数字都可以容纳 16 位,这里有一个解决方案来解决您的问题(仍然需要大量内存(:

import pandas as pd
import numpy as np
def gen_data(datelist, store_IDs, product_IDs):
date16 = np.arange(len(datelist), dtype=np.int16)
store16 = np.arange(len(store_IDs), dtype=np.int16)
product16 = np.arange(len(product_IDs), dtype=np.int16)
A = np.array(np.meshgrid(date16, store16, product16), dtype=np.int16).reshape(3,-1)
length = A.shape[1]
sales = np.random.randint(100, 1001, size=(1,length), dtype=np.int16)
sold = np.random.randint(1, 101, size=(1,length), dtype=np.int16)
data = np.concatenate((A,sales,sold), axis=0)
df = pd.DataFrame(data.T, columns=['Date index', 'Store ID index', 'Product ID index', 'Sales', 'Number of Products Sold'], dtype=np.int16)
return df

FWIW 在我的机器上,我获得:

Date  Store ID  Product ID  Sales  Number of Products Sold
0              0         0           0    127                       85
1              0         0           1    292                       37
2              0         0           2    180                       36
3              0         0           3    558                       88
4              0         0           4    519                       79
...          ...       ...         ...    ...                      ...
1137680572  1276        98        8994    932                       78
1137680573  1276        98        8995    401                       47
1137680574  1276        98        8996    840                       77
1137680575  1276        98        8997    717                       91
1137680576  1276        98        8998    632                       24
[1137680577 rows x 5 columns]
real    1m16.325s
user    0m22.086s
sys 0m25.800s

(我没有足够的内存并使用交换(

最新更新