2010-11-14 85 views
3

我想写一个函数,将采取选择满足条件的表中的第一个元素。例如,如果我给第一栏的时间和第二栏的感染人数给出如下表格,我想写一个论据,它会返回至少有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 

因此,从这张表格中,我希望arguemnt告诉我,在8秒钟内,至少有100人被感染。我尝试使用SELECT来做到这一点,但我不知道如何使用SELECT与2列的表,并让它根据第二列的条件返回第一列中的值。

+1

这真的是一个数学问题吗? – 2010-11-14 21:58:05

回答

2

这里有几个不同的方式来做到这一点,假设我理解正确的数据...

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 

我建议你阅读部分高达[]为了更好的理解。

3

使用替换规则的替代方案是

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。 我建议你阅读PatternsRules的教程。


编辑:ImportString作品对新格式的数据,以及 - 但你不再需要使用Partition

+0

+1,巧妙地使用模式。因为她只想要第一列的值,所以我会将你的模式改为'{___,{x_,_?(#> = 100&)},___}'。否则,没有改变。 – rcollyer 2010-11-15 03:56:55

+0

+1,因为替换规则通常比'Cases“,”Select“或”Position“快得多。 – Timo 2010-11-15 10:20:17

+0

@Timo模式匹配实际上比Joshua给出的Cases和Select慢得多,在这种情况下。 – 2011-03-04 14:10:25

3

你也可以使用一个简单的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 
1

我相信还有比已经给出什么更快的方法,但首先,约书亚的Cases方法可以通过使用/;而不是&进行快一点进行测试。

这是我提出解决方案(编辑:增加了对清晰的白色空间,因为双括号这里不格式化):

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

下面是提供的各种方法计时。请注意,/.方法只运行一次,其他运行方式则运行loops次。因此,在第一次测试中,它比Position方法慢100倍。此外,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