从 pandas 数据框指定的间隔内的列表中提取值
extract values from a list that falls in intervals specified by pandas dataframe
我有一个长度为 103237 的巨大列表。我有一个形状为 (8173,6) 的数据框。我想从 pandas 数据框中的两列 (1 AND 2) 指定的值之间的列表中提取这些值。例如:
lst = [182,73,137,1,938]
###dataframe
0 1 2 3 4
John 150 183 NY US
Peter 30 50 SE US
Stef 900 969 NY US
预期输出列表:
lst = [182,938]
由于 182 位于数据帧第一行的 150 和 183 之间,而 938 位于第 3 行的 900 和 969 之间,因此我希望新列表包含原始列表中的 182 和 938。为了解决这个问题,我将数据框转换为 numpy 数组:
nn = df.values()
new_list = []
for item in lst:
for i in range(nn.shape[0]):
if item >= nn[i][1] and item <= nn[i][2]:
new_list.append(item)
但上面提到的代码自 O(n^2) 以来花费了很长时间,而且它不能很好地扩展到我的列表,它有 103237 个项目。如何更有效地做到这一点?
您可以迭代列表并将每个元素与第 1 列和第 2 列的所有对进行比较,看看是否有任何对包含该元素。
[e for e in lst if (df['1'].lt(e) & df['2'].gt(e)).any()]
我用列表中的 110000 个元素和数据框中的 9000 行进行了测试,代码在 macbook pro 上 运行 需要 32 秒。
考虑以下问题:假设您有一个值 item
,您可以通过以下行询问是否在任何区间内
((df[1] <= item) & (df[2] >= item)).any()
语句 (df[1] <= item)
和 (df[2] >= item)
return true/false 的布尔数组。 '&' 将 return 一个布尔数组,无论 item
是否在特定区间内。如果布尔数组中有任何 True 值,则在最后 return 添加 any()
为 true,也就是如果有一个间隔为“True”(数字在间隔内)。
所以对于单个项目,您可以通过上面的行得到答案。
要扫描所有项目,您可以执行以下操作:
new_list = []
for item in lst:
if ((df[1] <= item) & (df[2] >= item)).any():
new_list.append(item)
或列表理解:
new_list = [item for item in lst if ((df[1] <= item) & (df[2] >= item)).any()]
编辑:如果此代码太慢,您可以使用 numba 进一步加速,但我相信使用 pandas 矢量化(又名使用 df[1]<=item
就足够了)
我有一个长度为 103237 的巨大列表。我有一个形状为 (8173,6) 的数据框。我想从 pandas 数据框中的两列 (1 AND 2) 指定的值之间的列表中提取这些值。例如:
lst = [182,73,137,1,938]
###dataframe
0 1 2 3 4
John 150 183 NY US
Peter 30 50 SE US
Stef 900 969 NY US
预期输出列表:
lst = [182,938]
由于 182 位于数据帧第一行的 150 和 183 之间,而 938 位于第 3 行的 900 和 969 之间,因此我希望新列表包含原始列表中的 182 和 938。为了解决这个问题,我将数据框转换为 numpy 数组:
nn = df.values()
new_list = []
for item in lst:
for i in range(nn.shape[0]):
if item >= nn[i][1] and item <= nn[i][2]:
new_list.append(item)
但上面提到的代码自 O(n^2) 以来花费了很长时间,而且它不能很好地扩展到我的列表,它有 103237 个项目。如何更有效地做到这一点?
您可以迭代列表并将每个元素与第 1 列和第 2 列的所有对进行比较,看看是否有任何对包含该元素。
[e for e in lst if (df['1'].lt(e) & df['2'].gt(e)).any()]
我用列表中的 110000 个元素和数据框中的 9000 行进行了测试,代码在 macbook pro 上 运行 需要 32 秒。
考虑以下问题:假设您有一个值 item
,您可以通过以下行询问是否在任何区间内
((df[1] <= item) & (df[2] >= item)).any()
语句 (df[1] <= item)
和 (df[2] >= item)
return true/false 的布尔数组。 '&' 将 return 一个布尔数组,无论 item
是否在特定区间内。如果布尔数组中有任何 True 值,则在最后 return 添加 any()
为 true,也就是如果有一个间隔为“True”(数字在间隔内)。
所以对于单个项目,您可以通过上面的行得到答案。
要扫描所有项目,您可以执行以下操作:
new_list = []
for item in lst:
if ((df[1] <= item) & (df[2] >= item)).any():
new_list.append(item)
或列表理解:
new_list = [item for item in lst if ((df[1] <= item) & (df[2] >= item)).any()]
编辑:如果此代码太慢,您可以使用 numba 进一步加速,但我相信使用 pandas 矢量化(又名使用 df[1]<=item
就足够了)