Выбор данных из таблицы в математике

Я пытаюсь написать функцию, которая будет выбирать первый элемент в таблице, который удовлетворяет критериям. Например, если мне присваивается следующая таблица со временем в первом столбце и числом людей, зараженных заболеванием, во втором, я хочу написать аргумент, который вернет время, когда инфицировано не менее 100 человек.

0   1
1   2
2   4
3   8
4   15
5   29
6   50
7   88
8   130
9   157
10  180
11  191
12  196
13  199
14  200

Итак, из этой таблицы, я хочу, чтобы аргумент не сказал мне, что через 8 секунд было инфицировано не менее 100 человек. Я попытался использовать SELECT для этого, но я не уверен, как использовать SELECT с таблицей из 2 столбцов и вернуть значение в первом столбце на основе критериев из второго столбца.

Ответ 1

Альтернативой, использующей правила замены, является

ImportString["0 1 1 2 2 4 3 8 4 15 5 29 6 50 7 88 8 130 9 157 10 180 11 191 12 196 13 199 14 200", "Table"];
Partition[Flatten[%], 2]
% /. {___, x : {_, _?(# >= 100 &)}, ___} :> x

Алгоритм, с помощью которого Mathematica ищет шаблоны, гарантирует, что это вернет первый такой случай. Если вам нужны все случаи, вы можете использовать ReplaceList. Я предлагаю вам прочитать учебник по Patterns и Rules.


Изменить: ImportString также работает с вновь отформатированными данными, но вам больше не нужно использовать Partition.

Ответ 2

Вы также можете использовать простой NestWhile

data = {{0,1},{1,2},{2,4},{3,8},{4,15},{5,29},{6,50},{7,88},{8,130},{9,157},{10,180},
 {11,191},{12,196},{13,199},{14,200}};
NestWhile[# + 1 &, 1, data[[#, 2]] < 100 &] - 1

Ответ 3

Вот несколько разных способов сделать это, предполагая, что я правильно интерпретировал ваши данные...

In[3]:= data = {{0,1},{1,2},{2,4},{3,8},{4,15},{5,29},{6,50},{7,88},{8,130},{9,157},{10,180},{11,191},{12,196},{13,199},{14,200}};

In[8]:= Cases[data, {_, _?(#>=100&)}, 1, 1][[1, 1]]
Out[8]= 8

In[9]:= Select[data, #[[2]]>=100&, 1][[1, 1]]
Out[9]= 8

Я предлагаю вам прочитать часть [], чтобы понять это лучше.

Ответ 4

Я считаю, что есть более быстрый способ, чем то, что уже было дано, но сначала метод Joshua Cases можно сделать немного быстрее, используя /;, а не & для теста.

Это решение, которое я предлагаю (редактирование: добавление пробела для ясности, поскольку двойные скобки не форматируются здесь):

dat[[
  Position[
    dat[[All, 2]],
    x_ /; x >= 100,
    1, 1
  ][[1, 1]],
  1
]]

Здесь приведены тайминги для различных предложенных методов. Обратите внимание, что метод /. запускается только один раз, а остальные запускаются loops раз. Поэтому в этом первом тесте он на 100 раз медленнее, чем метод Position. Кроме того, метод NestWhile возвращает только индекс, а не фактический первый элемент столбца.

In[]:= 
dat = {Range[5000], [email protected][1*^6, 5000]} // Transpose;
lim = 300000; loops = 100;
dat /. {___, {x_, _?(# >= lim &)}, ___} :> x; // Timing
Do[  Cases[dat, {_, _?(# >= lim &)}, 1, 1][[1, 1]]  , {loops}] // Timing
Do[  Cases[dat, {_, y_ /; y >= lim}, 1, 1][[1, 1]]  , {loops}] // Timing
Do[  Select[dat, #[[2]] >= lim &, 1][[1, 1]]  , {loops}] // Timing
Do[  NestWhile[# + 1 &, 1, dat[[#, 2]] < lim &]  , {loops}] // Timing
Do[  dat[[Position[dat[[All, 2]], x_ /; x >= lim, 1, 1][[1, 1]], 1]]  , {loops}] // Timing

Out[]= {0.125, Null}

Out[]= {0.438, Null}

Out[]= {0.406, Null}

Out[]= {0.469, Null}

Out[]= {0.281, Null}

Out[]= {0.125, Null}

С более длинной таблицей (я не использую медленный метод):

In[]:= 
dat = {Range[35000], [email protected][1*^6, 35000]} // Transpose;
lim = 300000; loops = 25;
Do[  Cases[dat, {_, _?(# >= lim &)}, 1, 1][[1, 1]]  , {loops}] // Timing
Do[  Cases[dat, {_, y_ /; y >= lim}, 1, 1][[1, 1]]  , {loops}] // Timing
Do[  Select[dat, #[[2]] >= lim &, 1][[1, 1]]  , {loops}] // Timing
Do[  NestWhile[# + 1 &, 1, dat[[#, 2]] < lim &]  , {loops}] // Timing
Do[  dat[[Position[dat[[All, 2]], x_ /; x >= lim, 1, 1][[1, 1]], 1]]  , {loops}] // Timing

Out[]= {0.734, Null}

Out[]= {0.641, Null}

Out[]= {0.734, Null}

Out[]= {0.5, Null}

Out[]= {0.266, Null}

Наконец, подтверждение соглашения:

In[]:= SameQ[
         Select[dat, #[[2]] >= lim &, 1][[1, 1]],
         dat[[Position[dat[[All, 2]], x_ /; x >= lim, 1, 1][[1, 1]], 1]]
       ]

Out[]= True