我有像
这样的数据[312.281,
370.401,
254.245,
272.256,
312.325,
286.243,
271.231, ...]
然后我想按照
的值范围对它们进行分组for i in data:
if i in range(200,300):
data_200_300.append(i)
elif i in range(300,400):
data_300_400.append(i)
它不起作用,我应该使用什么代码?
答案 0 :(得分:3)
range
返回两个数字之间的整数列表,而您的数据包含浮点数。您可以使用>
和<
直接使用Comparisons:
for i in data:
if 200 < i < 300:
data_200_300.append(i)
elif 300 < i < 400:
data_300_400.append(i)
如果您希望某些匹配包含在内,您也可以使用<=
。
答案 1 :(得分:1)
@AKS作为替代方案正确回答你也可以尝试使用 lambda表达式这样的东西。
result = filter(lambda x: 200 < x < 300, data)
您可以使用它来处理您的数据
filtered_data = []
for i in range(200,400,100):
filtered_data.append( filter(lambda x: i < x < i+100, data) )
>>> filtered_data
[[254.245, 272.256, 286.243, 271.231], [312.281, 370.401, 312.325]]
答案 2 :(得分:0)
如果你有很多这样的值并且可以导入numpy
,那么有一个比if-conditions或lambda-filter字符串更快的选项。它使用逻辑索引:
def indexingversion(data, bin_start, bin_end, bin_step):
x = np.array(data)
bin_edges = np.arange(bin_start, bin_end + bin_step, bin_step)
bin_number = bin_edges.size - 1
cond = np.zeros((x.size, bin_number), dtype=bool)
for i in range(bin_number):
cond[:, i] = np.logical_and(bin_edges[i] < x,
x < bin_edges[i+1])
return [list(x[cond[:, i]]) for i in range(bin_number)]
到目前为止,我已将所有解决方案和我的版本放在他们自己的函数中,并使用行分析器(rkern/line_profiler)一次性运行它们。 最后一行证明了所有三个输出都是相同的(这需要我的版本一点,因为我必须在开始和结束时转换为numpy数组)。
我的版本和lambda版本还有一个额外的好处,你也可以将它们分组到其他bin中,你必须在第一个解决方案中重写if
- 语句。
import numpy as np
def forloop(x):
data_200_300 = []
data_300_400 = []
for i in x:
if 200 < i < 300:
data_200_300.append(i)
elif 300 < i < 400:
data_300_400.append(i)
return [data_200_300, data_300_400]
def lambdaversion(data, bin_start, bin_end, bin_step):
filtered_data = []
for i in range(bin_start,bin_end,bin_step):
filtered_data.append( filter(lambda x: i < x < i+bin_step, data) )
return filtered_data
def indexingversion(data, bin_start, bin_end, bin_step):
x = np.array(data)
bin_edges = np.arange(bin_start, bin_end + bin_step, bin_step)
bin_number = bin_edges.size - 1
cond = np.zeros((x.size, bin_number), dtype=bool)
for i in range(bin_number):
cond[:, i] = np.logical_and(bin_edges[i] < x,
x < bin_edges[i+1])
return [list(x[cond[:, i]]) for i in range(bin_number)]
#@profile
def run_all():
n = 100000
x = np.random.random_integers(200, 400, n) + np.random.ranf(n)
bin_start = 200
bin_end = 400
bin_step = 100
a = forloop(x)
b = lambdaversion(x, bin_start, bin_end, bin_step)
c = indexingversion(x, bin_start, bin_end, bin_step)
print('All the same? - ' + str(a == b == c))
if __name__ == '__main__':
run_all()
分析输出:
All the same? - True
Wrote profile results to bla.py.lprof
Timer unit: 1e-06 s
Total time: 0.580098 s
File: bla.py
Function: run_all at line 32
Line # Hits Time Per Hit % Time Line Contents
==============================================================
32 @profile
33 def run_all():
34 1 1 1.0 0.0 n = 100000
35 1 3311 3311.0 0.6 x = np.random.random_integers(200, 400, n) + np.random.ranf(n)
36 1 2 2.0 0.0 bin_start = 200
37 1 1 1.0 0.0 bin_end = 400
38 1 0 0.0 0.0 bin_step = 100
39 1 263073 263073.0 45.3 a = forloop(x)
40 1 301819 301819.0 52.0 b = lambdaversion(x, bin_start, bin_end, bin_step)
41 1 7514 7514.0 1.3 c = indexingversion(x, bin_start, bin_end, bin_step)
42 1 4377 4377.0 0.8 print('All the same? - ' + str(a == b == c))
正如您所看到的(在Time
或% Time
列中),numpy-indexing的速度提高了40或50倍,至少对于100,000个数字。但是,对于非常少量的值,它的速度会慢一些(在我的机器上,它在大约40个值时开始变得更快)。