从带有描述的 Numpy nd 数组创建 Pandas DataFrame 的更快方法?
Faster way to create Pandas DataFrame from a Numpy nd array with descriptions?
我想将带有维度描述的 numpy nd 数组转换为 pandas 数据框。
以下解决方案有效,但对于 360000 行来说似乎有点慢(在我的机器上为 1.5s,您的结果可能不同)。
import pandas as pd
import numpy as np
from itertools import product
import time
# preparation of data
nd_data = np.random.random((5, 3, 100, 10, 4, 6))
dimension_descriptions = {
'floaty': [0.1,0.2,0.3,0.4,0.5],
'animal': ['ducks', 'horses', 'elephants'],
'ramp': range(100),
'another_ramp': range(10),
'interesting number': [12, 15, 29, 42],
'because': ['why', 'is', 'six', 'afraid', 'of', 'seven']
}
t_start = time.time()
# create dataframe from list of dictionairies containing data and permuted descriptions
df = pd.DataFrame([{**{'data': data}, **dict(zip(dimension_descriptions.keys(), permuted_description))}
for data, permuted_description in zip(nd_data.flatten(), product(*dimension_descriptions.values()))])
print(f'elapsed time: {time.time()- t_start:.1f}s')
有没有更快的方法达到相同的结果?
在我的机器上,我将创建 df 的原始方法放在一个函数中并对其进行计时。
def create_df1(nd_data, dimension_descriptions):
return pd.DataFrame([{**{'data': data}, **dict(zip(dimension_descriptions.keys(), permuted_description))}
for data, permuted_description in zip(nd_data.flatten(), product(*dimension_descriptions.values()))])
%timeit create_df1(nd_data, dimension_descriptions)
991 ms ± 37.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
您可以避免创建临时字典并将其添加到新字典,方法是在首次创建原始置换数据后将 nd_data
分配给 DataFrame。这会略微提高速度。
def create_df2(nd_data, dimension_descriptions):
df = pd.DataFrame([dict(zip(dimension_descriptions.keys(), permuted_description))
for permuted_description in product(*dimension_descriptions.values())])
df["data"] = nd_data.flatten()
return df
%timeit create_df2(nd_data, dimension_descriptions)
822 ms ± 42.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
如果您需要 data
列作为数据框中的第一列,您可以改用 df.insert(0, "data", nd_data.flatten())
,这在我的机器上获得了类似的速度结果。
每次创建具有相同列名的字典似乎也很浪费。 Pandas 提供了一种避免这种情况的方法,它允许您将列列表作为单独的参数传递,并且您可以将数据作为列表的列表传递。这样可以节省很多时间。
def create_df3(nd_data, dimension_descriptions):
df = pd.DataFrame(list(product(*dimension_descriptions.values())), columns=dimension_descriptions.keys())
df["data"] = nd_data.flatten()
return df
%timeit create_df3(nd_data, dimension_descriptions)
281 ms ± 9.88 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
我想将带有维度描述的 numpy nd 数组转换为 pandas 数据框。 以下解决方案有效,但对于 360000 行来说似乎有点慢(在我的机器上为 1.5s,您的结果可能不同)。
import pandas as pd
import numpy as np
from itertools import product
import time
# preparation of data
nd_data = np.random.random((5, 3, 100, 10, 4, 6))
dimension_descriptions = {
'floaty': [0.1,0.2,0.3,0.4,0.5],
'animal': ['ducks', 'horses', 'elephants'],
'ramp': range(100),
'another_ramp': range(10),
'interesting number': [12, 15, 29, 42],
'because': ['why', 'is', 'six', 'afraid', 'of', 'seven']
}
t_start = time.time()
# create dataframe from list of dictionairies containing data and permuted descriptions
df = pd.DataFrame([{**{'data': data}, **dict(zip(dimension_descriptions.keys(), permuted_description))}
for data, permuted_description in zip(nd_data.flatten(), product(*dimension_descriptions.values()))])
print(f'elapsed time: {time.time()- t_start:.1f}s')
有没有更快的方法达到相同的结果?
在我的机器上,我将创建 df 的原始方法放在一个函数中并对其进行计时。
def create_df1(nd_data, dimension_descriptions):
return pd.DataFrame([{**{'data': data}, **dict(zip(dimension_descriptions.keys(), permuted_description))}
for data, permuted_description in zip(nd_data.flatten(), product(*dimension_descriptions.values()))])
%timeit create_df1(nd_data, dimension_descriptions)
991 ms ± 37.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
您可以避免创建临时字典并将其添加到新字典,方法是在首次创建原始置换数据后将 nd_data
分配给 DataFrame。这会略微提高速度。
def create_df2(nd_data, dimension_descriptions):
df = pd.DataFrame([dict(zip(dimension_descriptions.keys(), permuted_description))
for permuted_description in product(*dimension_descriptions.values())])
df["data"] = nd_data.flatten()
return df
%timeit create_df2(nd_data, dimension_descriptions)
822 ms ± 42.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
如果您需要 data
列作为数据框中的第一列,您可以改用 df.insert(0, "data", nd_data.flatten())
,这在我的机器上获得了类似的速度结果。
每次创建具有相同列名的字典似乎也很浪费。 Pandas 提供了一种避免这种情况的方法,它允许您将列列表作为单独的参数传递,并且您可以将数据作为列表的列表传递。这样可以节省很多时间。
def create_df3(nd_data, dimension_descriptions):
df = pd.DataFrame(list(product(*dimension_descriptions.values())), columns=dimension_descriptions.keys())
df["data"] = nd_data.flatten()
return df
%timeit create_df3(nd_data, dimension_descriptions)
281 ms ± 9.88 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)