对大量数据使用 python 个生成器
Using python generators with lots of data
我有一个包含 25 万个项目的数据集,这些项目在添加到 list/generator 之前需要满足特定条件。为了加快处理速度,我想使用生成器,但我不确定是否使用生成过滤样本的函数来过滤数据,或者我是否应该 return 过滤样本到生成器对象等. 我希望最终对象只包含满足过滤条件的样本,但默认情况下 python 将 return/yield 一个 NoneType 对象。我已经包含示例过滤器函数、数据(真正的问题使用字符串,但为了简单起见,我使用来自随机正态分布的浮点数),以及我打算如何处理下面的数据。
在这种情况下我应该如何有效地使用生成器?为此目的甚至 logical/efficient 使用生成器吗?我知道我可以检查 return 函数中的元素是否为 None 以将其从容器中排除 (list/generator),但是我如何使用生成的函数执行此操作价值观?
# For random data
import numpy as np
# Functions
def filter_and_yield(item_in_data):
if item_in_data > 0.0:
yield item_in_data
def filter_and_return(item_in_data):
if item_in_data > 0.0:
return item_in_data
# Arbitrary data
num_samples = 250 * 10**3
data = np.random.normal(size=(num_samples,))
# Should I use this: generator with generator elements?
filtered_data_as_gen_with_gen_elements = (filter_and_yield(item) for item in data)
# Should I use this: list with generator elements?
filtered_data_as_lst_with_gen_elements = [filter_and_yield(item) for item in data]
# Should I use this: generator with non-generator elements?
filtered_data_as_gen_with_non_gen_elements = (
filter_and_return(item) for item in data if filter_and_return(item) is not None)
# Should I use this: list with non-generator elements?
filtered_data_as_lst_with_non_gen_elements = [
filter_and_return(item) for item in data if filter_and_return(item) is not None]
# Saving the data as csv -- note, `filtered_data` is NOT defined
# but is a place holder for whatever correct way of filtering the data is
df = pd.DataFrame({'filtered_data': filtered_data})
df.to_csv('./filtered_data.csv')
简短的回答是 none 这些是最好的。 Numpy 和 pandas 包括大量 C 和 Fortan 代码,这些代码适用于存储在连续数组中的硬件级数据类型。 Python 对象,即使是像 int
和 float
这样的低级别对象也相对笨重。它们包括标准的 python 对象头并分配在堆上。甚至像 >
这样的简单操作也需要调用其中一种方法。
最好尽可能使用 numpy/pandas 函数和运算符。这些包已经重载了标准 python 运算符以在一次调用中处理整组数据。
df = pd.DataFrame({'filtered_data': data[data > 0.0]})
此处,data > 0.0
创建了一个新的 true/false numpy 数组用于比较。 data[...]
创建了一个新数组,其中仅包含 data
的值,这些值也是正确的。
其他说明
filter_and_yield
是一个生成器,它将迭代 0 或 1 个值。 Python 把它变成了一个发电机,因为它有一个 yield
。当它 returns None
时, python 将其变成 StopIteration
异常。该生成器的消费者将看不到 None
.
(filter_and_yield(item) for item in data)
是 returns 个生成器。如果你使用它,你最终会得到生成器的数据框列。
[filter_and_yield(item) for item in data]
是一个生成器列表(因为 filter_and_yield 是一个生成器)。当 pandas 创建一个列时,它需要知道列的大小。因此它将生成器扩展为列表,就像您在此处所做的那样。你可以为 pandas 做这个,这并不重要。除了 pandas 完成后会删除该列表,从而减少内存使用量。
(filter_and_return(item) for item in data if filter_and_return(item) is not None)
这个可以用,但是很慢。 data
保存硬件级别的整数数组。 for item in data
必须将这些整数中的每一个转换为 python 级整数,而 nfilter_and_return(item)
是一个相对昂贵的函数调用。这可以重写为 (value for value in (filter_and_return(item) for item in data) if value is not None)
以将函数调用次数减半。
[filter_and_return(item) for item in data if filter_and_return(item) is not None]
如上所述。可以这样做,但是完成后删除以节省内存。
我有一个包含 25 万个项目的数据集,这些项目在添加到 list/generator 之前需要满足特定条件。为了加快处理速度,我想使用生成器,但我不确定是否使用生成过滤样本的函数来过滤数据,或者我是否应该 return 过滤样本到生成器对象等. 我希望最终对象只包含满足过滤条件的样本,但默认情况下 python 将 return/yield 一个 NoneType 对象。我已经包含示例过滤器函数、数据(真正的问题使用字符串,但为了简单起见,我使用来自随机正态分布的浮点数),以及我打算如何处理下面的数据。
在这种情况下我应该如何有效地使用生成器?为此目的甚至 logical/efficient 使用生成器吗?我知道我可以检查 return 函数中的元素是否为 None 以将其从容器中排除 (list/generator),但是我如何使用生成的函数执行此操作价值观?
# For random data
import numpy as np
# Functions
def filter_and_yield(item_in_data):
if item_in_data > 0.0:
yield item_in_data
def filter_and_return(item_in_data):
if item_in_data > 0.0:
return item_in_data
# Arbitrary data
num_samples = 250 * 10**3
data = np.random.normal(size=(num_samples,))
# Should I use this: generator with generator elements?
filtered_data_as_gen_with_gen_elements = (filter_and_yield(item) for item in data)
# Should I use this: list with generator elements?
filtered_data_as_lst_with_gen_elements = [filter_and_yield(item) for item in data]
# Should I use this: generator with non-generator elements?
filtered_data_as_gen_with_non_gen_elements = (
filter_and_return(item) for item in data if filter_and_return(item) is not None)
# Should I use this: list with non-generator elements?
filtered_data_as_lst_with_non_gen_elements = [
filter_and_return(item) for item in data if filter_and_return(item) is not None]
# Saving the data as csv -- note, `filtered_data` is NOT defined
# but is a place holder for whatever correct way of filtering the data is
df = pd.DataFrame({'filtered_data': filtered_data})
df.to_csv('./filtered_data.csv')
简短的回答是 none 这些是最好的。 Numpy 和 pandas 包括大量 C 和 Fortan 代码,这些代码适用于存储在连续数组中的硬件级数据类型。 Python 对象,即使是像 int
和 float
这样的低级别对象也相对笨重。它们包括标准的 python 对象头并分配在堆上。甚至像 >
这样的简单操作也需要调用其中一种方法。
最好尽可能使用 numpy/pandas 函数和运算符。这些包已经重载了标准 python 运算符以在一次调用中处理整组数据。
df = pd.DataFrame({'filtered_data': data[data > 0.0]})
此处,data > 0.0
创建了一个新的 true/false numpy 数组用于比较。 data[...]
创建了一个新数组,其中仅包含 data
的值,这些值也是正确的。
其他说明
filter_and_yield
是一个生成器,它将迭代 0 或 1 个值。 Python 把它变成了一个发电机,因为它有一个 yield
。当它 returns None
时, python 将其变成 StopIteration
异常。该生成器的消费者将看不到 None
.
(filter_and_yield(item) for item in data)
是 returns 个生成器。如果你使用它,你最终会得到生成器的数据框列。
[filter_and_yield(item) for item in data]
是一个生成器列表(因为 filter_and_yield 是一个生成器)。当 pandas 创建一个列时,它需要知道列的大小。因此它将生成器扩展为列表,就像您在此处所做的那样。你可以为 pandas 做这个,这并不重要。除了 pandas 完成后会删除该列表,从而减少内存使用量。
(filter_and_return(item) for item in data if filter_and_return(item) is not None)
这个可以用,但是很慢。 data
保存硬件级别的整数数组。 for item in data
必须将这些整数中的每一个转换为 python 级整数,而 nfilter_and_return(item)
是一个相对昂贵的函数调用。这可以重写为 (value for value in (filter_and_return(item) for item in data) if value is not None)
以将函数调用次数减半。
[filter_and_return(item) for item in data if filter_and_return(item) is not None]
如上所述。可以这样做,但是完成后删除以节省内存。