【问题标题】:Get Start and Stop Values For Incrementing Groups in NumPy Vector获取 NumPy 向量中递增组的开始和停止值
【发布时间】:2020-02-19 05:24:11
【问题描述】:

我有一个 NumPy 向量,它已排序并且不包含重复,例如:

[  1,   2,   6,  12,  13,  14,  16,  18,  19,  22,  23,  26,  29,
  31,  32,  34,  37,  38,  39,  40,  42,  43,  44,  49,  50,  52,
  55,  63,  64,  67,  68,  75,  78,  82,  84,  86,  88,  90,  93,
  95,  97,  98, 100, 103, 104, 106, 114, 119, 123, 124, 127, 129,
 130, 131, 134, 137, 139, 141, 142, 146, 149, 151, 153, 154, 155,
 159, 160, 161, 162, 165, 166, 167, 171, 173, 180, 181, 184, 186,
 189, 191, 194, 195, 196, 202, 208, 210, 212, 215, 216, 218, 223,
 224, 225, 226, 231, 233, 235, 239, 240, 241, 245, 248, 252, 253,
 259, 260, 261, 264, 271, 272, 273, 276, 279, 280, 285, 287, 290,
 291, 292, 293, 296, 297, 301, 304, 306, 307, 311, 312, 313, 319,
 320, 323, 324, 325, 326, 332, 335, 336, 337, 338, 339, 341, 342,
 345, 346, 349, 352, 355, 359, 364, 365, 367, 369, 373, 376, 378,
 380, 382, 386, 387, 388, 391, 399, 400, 401, 405, 408, 409, 410,
 413, 414, 415, 416, 423, 427, 428, 429, 432, 433, 434, 435, 437,
 439, 440, 443, 448, 449, 451, 453, 455, 459, 461, 464, 465, 466,
 467, 468, 470, 471, 473, 476, 478, 482, 487, 488, 491, 495, 498,
 501, 502, 503, 505, 506, 507, 514, 518, 519, 520, 522, 523, 525,
 528, 530, 532, 534, 538, 539, 540, 544, 550, 551, 556, 558, 568,
 571, 573, 577, 578, 582, 584, 585, 592, 597, 599, 603, 605, 607,
 609, 610, 612, 616, 618, 621, 623, 625, 626, 628, 630, 631, 632,
 633, 636, 637, 639, 642, 644, 647, 651, 653, 654, 656, 661, 662,
 666, 668, 670, 672, 673, 674, 675, 676, 682, 684, 687, 688, 690,
 692, 693, 694, 696, 697, 698, 699, 705, 706, 707, 708, 713, 714,
 719, 726, 727, 729, 730, 736, 737, 739, 740, 741, 742, 744, 748,
 749, 753, 758, 759, 762, 766, 771, 772, 774, 775, 778, 780, 782,
 786, 787, 789, 791, 793, 796, 797, 798, 799, 803, 804, 807, 809,
 811, 814, 815, 817, 819, 821, 827, 831, 833, 837, 842, 846, 849,
 851, 854, 855, 858, 865, 866, 867, 868, 870, 872, 873, 874, 880,
 881, 882, 884, 885, 890, 892, 893, 894, 895, 896, 897, 899, 900,
 902, 908, 912, 913, 915, 916, 920, 921, 924, 927, 930, 933, 941,
 942, 946, 950, 953, 957, 960, 963, 964, 967, 969, 972, 973, 975,
 978, 981, 983, 985, 986, 991, 992, 993, 995]

我需要的是找到存在连续(加一)数字的开始和停止值。所以输出会是这样的:

[[  1,  2],
 [  6,  6],
 [ 12, 14],
 [ 16, 16],
 [ 18, 19],
 [ 22, 23],
 [ 26, 26],
 [ 29, 29],
 [ 31, 32],
 [ 34, 34],
 [ 37, 40],
 [ 42, 44],
 .
 .
 .]

我认为我可以执行类似(x[:-1] - x[1:]) == 1 的操作来构建True/False 向量,但随后我必须遍历该向量来识别start/stop 值。我似乎无法提出除此之外的矢量化解决方案。

【问题讨论】:

标签: python numpy


【解决方案1】:

如果你的输入被称为x:

r = np.full(len(x),2)
d = np.diff(x)==1
r[1:]-=d
r[:-1]-=d 
np.repeat(x,r).reshape(-1,2)

输出:

array([[  1,   2],
       [  6,   6],
       [ 12,  14],
       [ 16,  16],
...

这通过重复每个项目两次(默认)但每个左或右直接邻居减去 1 次来工作:所以如果我在拉伸的左端或右端,我会重复一次,如果我在里面我重复零次。

【讨论】:

  • 这是什么魔法?!这很棒。谢谢
  • @slaw 我会添加一些解释。顺便提一句。您可以通过在最后一行使用 r&1 而不是 r 来摆脱单元素组。
  • 啊,如果我想删除或忽略 [6, 6][16, 16] 之类的单个事件,那就是 np.repeat(x, r & 1).reshape(-1, 2)
  • @slaw 没错。
  • 太棒了!在相关的说明中,有没有办法修改它,以便我们可以接受 min_run 值,以便它自动返回具有最小运行长度的 start/stop 值?所以min_run=2 将返回将返回最小运行长度为 2 的所有内容,min_run=3 将返回最小运行长度为 3 的所有内容,依此类推。现在,我只需将输出从第 1 列中减去第 2 列,然后将其与 min_run 进行比较,然后仅选择输出中列差等于或大于 min_run 的行。
【解决方案2】:

IIUC,你可以试试这样的:

arr = np.array([  1,   2,   6,  12,  13,  14,  16,  18,  19,  22,  23,  26,  29,
  31,  32,  34,  37,  38,  39,  40,  42,  43,  44,  49,  50,  52,
  55,  63,  64,  67,  68,  75,  78,  82,  84,  86,  88,  90,  93,
  95,  97,  98, 100, 103, 104, 106, 114, 119, 123, 124, 127, 129,
 130, 131, 134, 137, 139, 141, 142, 146, 149, 151, 153, 154, 155,
 159, 160, 161, 162, 165, 166, 167, 171, 173, 180, 181, 184, 186,
 189, 191, 194, 195, 196, 202, 208, 210, 212, 215, 216, 218, 223,
 224, 225, 226, 231, 233, 235, 239, 240, 241, 245, 248, 252, 253,
 259, 260, 261, 264, 271, 272, 273, 276, 279, 280, 285, 287, 290,
 291, 292, 293, 296, 297, 301, 304, 306, 307, 311, 312, 313, 319,
 320, 323, 324, 325, 326, 332, 335, 336, 337, 338, 339, 341, 342,
 345, 346, 349, 352, 355, 359, 364, 365, 367, 369, 373, 376, 378,
 380, 382, 386, 387, 388, 391, 399, 400, 401, 405, 408, 409, 410,
 413, 414, 415, 416, 423, 427, 428, 429, 432, 433, 434, 435, 437,
 439, 440, 443, 448, 449, 451, 453, 455, 459, 461, 464, 465, 466,
 467, 468, 470, 471, 473, 476, 478, 482, 487, 488, 491, 495, 498,
 501, 502, 503, 505, 506, 507, 514, 518, 519, 520, 522, 523, 525,
 528, 530, 532, 534, 538, 539, 540, 544, 550, 551, 556, 558, 568,
 571, 573, 577, 578, 582, 584, 585, 592, 597, 599, 603, 605, 607,
 609, 610, 612, 616, 618, 621, 623, 625, 626, 628, 630, 631, 632,
 633, 636, 637, 639, 642, 644, 647, 651, 653, 654, 656, 661, 662,
 666, 668, 670, 672, 673, 674, 675, 676, 682, 684, 687, 688, 690,
 692, 693, 694, 696, 697, 698, 699, 705, 706, 707, 708, 713, 714,
 719, 726, 727, 729, 730, 736, 737, 739, 740, 741, 742, 744, 748,
 749, 753, 758, 759, 762, 766, 771, 772, 774, 775, 778, 780, 782,
 786, 787, 789, 791, 793, 796, 797, 798, 799, 803, 804, 807, 809,
 811, 814, 815, 817, 819, 821, 827, 831, 833, 837, 842, 846, 849,
 851, 854, 855, 858, 865, 866, 867, 868, 870, 872, 873, 874, 880,
 881, 882, 884, 885, 890, 892, 893, 894, 895, 896, 897, 899, 900,
 902, 908, 912, 913, 915, 916, 920, 921, 924, 927, 930, 933, 941,
 942, 946, 950, 953, 957, 960, 963, 964, 967, 969, 972, 973, 975,
 978, 981, 983, 985, 986, 991, 992, 993, 995])

grp = np.cumsum(np.diff(np.append(0,arr))!=1)

[i[np.r_[0,-1]] 
    for i in np.split(arr, np.cumsum(np.unique(grp, return_counts=True)[1]))[:-1]]

输出:

[array([1, 2]),
 array([6, 6]),
 array([12, 14]),
 array([16, 16]),
 array([18, 19]),
 array([22, 23]),
 array([26, 26]),
 array([29, 29]),
 array([31, 32]),
 array([34, 34]),
 array([37, 40]),
 array([42, 44]),
 array([49, 50]),
 array([52, 52]),
 array([55, 55]),
 array([63, 64]),
 array([67, 68]),
 array([75, 75]),
 array([78, 78]),
 array([82, 82]),
 array([84, 84]),
 array([86, 86]),
 array([88, 88]),
 array([90, 90]),
 array([93, 93]),
 array([95, 95]),
 array([97, 98]),
 array([100, 100]),
 array([103, 104]),
 array([106, 106]),
 array([114, 114]),
 array([119, 119]),
 array([123, 124]),
 array([127, 127]),
 array([129, 131]),
 array([134, 134]),
 array([137, 137]),
 array([139, 139]),
 array([141, 142]),
 array([146, 146]),
 array([149, 149]),
 array([151, 151]),
 array([153, 155]),
 array([159, 162]),
 array([165, 167]),
 array([171, 171]),
 array([173, 173]),
 array([180, 181]),
 array([184, 184]),
 array([186, 186]),
 array([189, 189]),
 array([191, 191]),
 array([194, 196]),
 array([202, 202]),
 array([208, 208]),
 array([210, 210]),
 array([212, 212]),
 array([215, 216]),
 array([218, 218]),
 array([223, 226]),
 array([231, 231]),
 array([233, 233]),
 array([235, 235]),
 array([239, 241]),
 array([245, 245]),
 array([248, 248]),
 array([252, 253]),
 array([259, 261]),
 array([264, 264]),
 array([271, 273]),
 array([276, 276]),
 array([279, 280]),
 array([285, 285]),
 array([287, 287]),
 array([290, 293]),
 array([296, 297]),
 array([301, 301]),
 array([304, 304]),
 array([306, 307]),
 array([311, 313]),
 array([319, 320]),
 array([323, 326]),
 array([332, 332]),
 array([335, 339]),
 array([341, 342]),
 array([345, 346]),
 array([349, 349]),
 array([352, 352]),
 array([355, 355]),
 array([359, 359]),
 array([364, 365]),
 array([367, 367]),
 array([369, 369]),
 array([373, 373]),
 array([376, 376]),
 array([378, 378]),
 array([380, 380]),
 array([382, 382]),
 array([386, 388]),
 array([391, 391]),
 array([399, 401]),
 array([405, 405]),
 array([408, 410]),
 array([413, 416]),
 array([423, 423]),
 array([427, 429]),
 array([432, 435]),
 array([437, 437]),
 array([439, 440]),
 array([443, 443]),
 array([448, 449]),
 array([451, 451]),
 array([453, 453]),
 array([455, 455]),
 array([459, 459]),
 array([461, 461]),
 array([464, 468]),
 array([470, 471]),
 array([473, 473]),
 array([476, 476]),
 array([478, 478]),
 array([482, 482]),
 array([487, 488]),
 array([491, 491]),
 array([495, 495]),
 array([498, 498]),
 array([501, 503]),
 array([505, 507]),
 array([514, 514]),
 array([518, 520]),
 array([522, 523]),
 array([525, 525]),
 array([528, 528]),
 array([530, 530]),
 array([532, 532]),
 array([534, 534]),
 array([538, 540]),
 array([544, 544]),
 array([550, 551]),
 array([556, 556]),
 array([558, 558]),
 array([568, 568]),
 array([571, 571]),
 array([573, 573]),
 array([577, 578]),
 array([582, 582]),
 array([584, 585]),
 array([592, 592]),
 array([597, 597]),
 array([599, 599]),
 array([603, 603]),
 array([605, 605]),
 array([607, 607]),
 array([609, 610]),
 array([612, 612]),
 array([616, 616]),
 array([618, 618]),
 array([621, 621]),
 array([623, 623]),
 array([625, 626]),
 array([628, 628]),
 array([630, 633]),
 array([636, 637]),
 array([639, 639]),
 array([642, 642]),
 array([644, 644]),
 array([647, 647]),
 array([651, 651]),
 array([653, 654]),
 array([656, 656]),
 array([661, 662]),
 array([666, 666]),
 array([668, 668]),
 array([670, 670]),
 array([672, 676]),
 array([682, 682]),
 array([684, 684]),
 array([687, 688]),
 array([690, 690]),
 array([692, 694]),
 array([696, 699]),
 array([705, 708]),
 array([713, 714]),
 array([719, 719]),
 array([726, 727]),
 array([729, 730]),
 array([736, 737]),
 array([739, 742]),
 array([744, 744]),
 array([748, 749]),
 array([753, 753]),
 array([758, 759]),
 array([762, 762]),
 array([766, 766]),
 array([771, 772]),
 array([774, 775]),
 array([778, 778]),
 array([780, 780]),
 array([782, 782]),
 array([786, 787]),
 array([789, 789]),
 array([791, 791]),
 array([793, 793]),
 array([796, 799]),
 array([803, 804]),
 array([807, 807]),
 array([809, 809]),
 array([811, 811]),
 array([814, 815]),
 array([817, 817]),
 array([819, 819]),
 array([821, 821]),
 array([827, 827]),
 array([831, 831]),
 array([833, 833]),
 array([837, 837]),
 array([842, 842]),
 array([846, 846]),
 array([849, 849]),
 array([851, 851]),
 array([854, 855]),
 array([858, 858]),
 array([865, 868]),
 array([870, 870]),
 array([872, 874]),
 array([880, 882]),
 array([884, 885]),
 array([890, 890]),
 array([892, 897]),
 array([899, 900]),
 array([902, 902]),
 array([908, 908]),
 array([912, 913]),
 array([915, 916]),
 array([920, 921]),
 array([924, 924]),
 array([927, 927]),
 array([930, 930]),
 array([933, 933]),
 array([941, 942]),
 array([946, 946]),
 array([950, 950]),
 array([953, 953]),
 array([957, 957]),
 array([960, 960]),
 array([963, 964]),
 array([967, 967]),
 array([969, 969]),
 array([972, 973]),
 array([975, 975]),
 array([978, 978]),
 array([981, 981]),
 array([983, 983]),
 array([985, 986]),
 array([991, 993]),
 array([995, 995])]
​

【讨论】:

    【解决方案3】:

    similar answer for identifying consecutive zeros 提供以下功能:

    def zero_runs(a):  # from link
        iszero = np.concatenate(([0], np.equal(a, 0).view(np.int8), [0]))
        absdiff = np.abs(np.diff(iszero))
        ranges = np.where(absdiff == 1)[0].reshape(-1, 2)
        return ranges
    

    所以,我们可以这样做:

    x = np.array(
    [  1,   2,   6,  12,  13,  14,  16,  18,  19,  22,  23,  26,  29,
      31,  32,  34,  37,  38,  39,  40,  42,  43,  44,  49,  50,  52,
      55,  63,  64,  67,  68,  75,  78,  82,  84,  86,  88,  90,  93,
      95,  97,  98, 100, 103, 104, 106, 114, 119, 123, 124, 127, 129,
     130, 131, 134, 137, 139, 141, 142, 146, 149, 151, 153, 154, 155,
     159, 160, 161, 162, 165, 166, 167, 171, 173, 180, 181, 184, 186,
     189, 191, 194, 195, 196, 202, 208, 210, 212, 215, 216, 218, 223,
     224, 225, 226, 231, 233, 235, 239, 240, 241, 245, 248, 252, 253,
     259, 260, 261, 264, 271, 272, 273, 276, 279, 280, 285, 287, 290,
     291, 292, 293, 296, 297, 301, 304, 306, 307, 311, 312, 313, 319,
     320, 323, 324, 325, 326, 332, 335, 336, 337, 338, 339, 341, 342,
     345, 346, 349, 352, 355, 359, 364, 365, 367, 369, 373, 376, 378,
     380, 382, 386, 387, 388, 391, 399, 400, 401, 405, 408, 409, 410,
     413, 414, 415, 416, 423, 427, 428, 429, 432, 433, 434, 435, 437,
     439, 440, 443, 448, 449, 451, 453, 455, 459, 461, 464, 465, 466,
     467, 468, 470, 471, 473, 476, 478, 482, 487, 488, 491, 495, 498,
     501, 502, 503, 505, 506, 507, 514, 518, 519, 520, 522, 523, 525,
     528, 530, 532, 534, 538, 539, 540, 544, 550, 551, 556, 558, 568,
     571, 573, 577, 578, 582, 584, 585, 592, 597, 599, 603, 605, 607,
     609, 610, 612, 616, 618, 621, 623, 625, 626, 628, 630, 631, 632,
     633, 636, 637, 639, 642, 644, 647, 651, 653, 654, 656, 661, 662,
     666, 668, 670, 672, 673, 674, 675, 676, 682, 684, 687, 688, 690,
     692, 693, 694, 696, 697, 698, 699, 705, 706, 707, 708, 713, 714,
     719, 726, 727, 729, 730, 736, 737, 739, 740, 741, 742, 744, 748,
     749, 753, 758, 759, 762, 766, 771, 772, 774, 775, 778, 780, 782,
     786, 787, 789, 791, 793, 796, 797, 798, 799, 803, 804, 807, 809,
     811, 814, 815, 817, 819, 821, 827, 831, 833, 837, 842, 846, 849,
     851, 854, 855, 858, 865, 866, 867, 868, 870, 872, 873, 874, 880,
     881, 882, 884, 885, 890, 892, 893, 894, 895, 896, 897, 899, 900,
     902, 908, 912, 913, 915, 916, 920, 921, 924, 927, 930, 933, 941,
     942, 946, 950, 953, 957, 960, 963, 964, 967, 969, 972, 973, 975,
     978, 981, 983, 985, 986, 991, 992, 993, 995]
    )
    
    indices = zero_runs(np.diff(x)-1)
    
    out = np.vstack((y[inx[:, 0]], y[inx[:, 1]])).T
    

    out 只返回有运行的地方(而不是单个值,这是我想要的):

    array([[  1,   2],
           [ 12,  14],
           [ 18,  19],
           [ 22,  23],
           [ 31,  32],
           [ 37,  40],
           [ 42,  44],
           [ 49,  50],
           [ 63,  64],
           [ 67,  68],
           [ 97,  98],
           [103, 104],
           [123, 124],
           [129, 131],
           [141, 142],
           [153, 155],
           [159, 162],
           [165, 167],
           [180, 181],
           [194, 196],
           [215, 216],
           [223, 226],
           [239, 241],
           [252, 253],
           [259, 261],
           [271, 273],
           [279, 280],
           [290, 293],
           [296, 297],
           [306, 307],
           [311, 313],
           [319, 320],
           [323, 326],
           [335, 339],
           [341, 342],
           [345, 346],
           [364, 365],
           [386, 388],
           [399, 401],
           [408, 410],
           [413, 416],
           [427, 429],
           [432, 435],
           [439, 440],
           [448, 449],
           [464, 468],
           [470, 471],
           [487, 488],
           [501, 503],
           [505, 507],
           [518, 520],
           [522, 523],
           [538, 540],
           [550, 551],
           [577, 578],
           [584, 585],
           [609, 610],
           [625, 626],
           [630, 633],
           [636, 637],
           [653, 654],
           [661, 662],
           [672, 676],
           [687, 688],
           [692, 694],
           [696, 699],
           [705, 708],
           [713, 714],
           [726, 727],
           [729, 730],
           [736, 737],
           [739, 742],
           [748, 749],
           [758, 759],
           [771, 772],
           [774, 775],
           [786, 787],
           [796, 799],
           [803, 804],
           [814, 815],
           [854, 855],
           [865, 868],
           [872, 874],
           [880, 882],
           [884, 885],
           [892, 897],
           [899, 900],
           [912, 913],
           [915, 916],
           [920, 921],
           [941, 942],
           [963, 964],
           [972, 973],
           [985, 986],
           [991, 993]])
    

    【讨论】:

      猜你喜欢
      • 2017-03-30
      • 1970-01-01
      • 2017-01-18
      • 2013-02-10
      • 1970-01-01
      • 2020-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多