如何根据值的范围对数据进行分组

时间:2016-06-08 05:20:17

标签: python python-2.7

我有像

这样的数据
[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)

它不起作用,我应该使用什么代码?

3 个答案:

答案 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个值时开始变得更快)。