Получить начальные и конечные значения для возрастающих групп в NumPy Vector - PullRequest
2 голосов
/ 18 февраля 2020

У меня есть вектор 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, но тогда мне пришлось бы l oop через этот вектор для определения значений start / stop. Я не могу придумать векторизованное решение, кроме этого.

Ответы [ 3 ]

2 голосов
/ 19 февраля 2020

Если ваш ввод называется 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 раз для каждого левого или правый прямой сосед: так что, если я нахожусь на левом или правом конце отрезка, меня повторяют один раз, если я внутри, повторяю ноль раз.

1 голос
/ 18 февраля 2020

IIU C, вы можете попробовать что-то вроде этого:

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])]
​
0 голосов
/ 19 февраля 2020

A аналогичный ответ для определения последовательных нулей предлагает следующую функцию:

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]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...