将基于行的函数应用于子集

时间:2014-01-29 14:19:26

标签: r tapply

我是tapply函数的新手,并没有成功计算每个被询问子集中的时差计算。

我有一个输入数据框,其中包含某些RN的观察日期(列DATE)。在我的脚本中,我将这个数据框子化为另一个(让我们称之为DF)将数据限制为只有一个RN。

我正在尝试自动计算日期和上一个日期之间的差异。我可以使用以下代码在DF上执行此操作:

as.numeric(c(NA, as.Date(tail(DF$DATE,-1)) - as.Date(head(DF$DATE,-1)) ))

我需要根据3个变量(VAR1VAR2VAR3)在每个子集中运行此项,因此我尝试了所谓的tapply

我尝试过:(DATE是我的第三栏)

tapply(DF$DATE, list(DF$SITE, DF$YEAR, DF$SP), FUN =  function(x){
as.numeric(c(NA, as.Date(tail(DF[x,3],-1)) - as.Date(head(DF[x,3],-1))))})

我可能会错过这里的重点,因为它会返回一个填充了NULL的TONS的数组。最糟糕的是,它会返回NULL所有网站的DF数据。

该函数如何调用因输入中不均匀的因子水平?有没有办法跳过所有这些NULL数据,或至少限制它在我的子集的边界。

我搜索了SO和其他帮助网站,但没有找到合适的答案。

第二个问题:我想在新专栏中写出输出(时差)。由于tapply结果是数组,我该怎么做?我该把命令放在哪里?在function(x){}部分或apply命令之外?

编辑:这是DF的一部分,我也编辑了命令 EDIT2:在做dput我看到gthat所有我的因素水平仍然存在。我用factor()删除它们,但现在tapply()不再起作用了。

编辑3:@sgibb:我尝试了你的命令,但现在又出现了另一个错误:“as.Date.numeric(value)中的错误:'origin'必须提供”。所以我试图提供一个来源,如下图所示,但仍然有错误

SUBTOT$DIFF <- ave(SUBTOT$DATE, SUBTOT$SITE, SUBTOT$YEAR, SUBTOT$SP, FUN=function(x) {
as.numeric(c(NA, as.Date(tail(x,-1),origin="1960-10-01") -      as.Date(head(x,-1),origin="1960-10-01")))})


dput(head(SUBTOT,n=100))
structure(list(YEAR = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c("1994", 
"1995", "1996", "1997", "1998", "1999", "2000", "2001", "2002", 
"2003", "2004", "2005", "2006", "2007", "2008", "2009", "2010", 
"2011", "2012"), class = "factor"), RN = structure(c(1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L), .Label = "RNN144", class = "factor"), DATE = c("1994-04-16", 
"1994-07-23", "1994-10-01", "1994-04-16", "1994-05-07", "1994-10-01", 
"1994-04-16", "1994-07-05", "1994-07-10", "1994-07-17", "1994-10-01", 
"1994-04-16", "1994-06-20", "1994-10-01", "1994-04-16", "1994-06-06", 
"1994-10-01", "1994-04-16", "1994-07-23", "1994-10-01", "1994-04-16", 
"1994-09-19", "1994-09-24", "1994-10-01", "1994-04-16", "1994-04-23", 
"1994-04-30", "1994-05-07", "1994-05-23", "1994-05-29", "1994-07-10", 
"1994-07-17", "1994-07-23", "1994-08-08", "1994-10-01", "1994-04-16", 
"1994-07-17", "1994-07-23", "1994-10-01", "1994-04-16", "1994-07-17", 
"1994-10-01", "1994-04-16", "1994-07-05", "1994-07-10", "1994-07-17", 
"1994-07-23", "1994-08-20", "1994-10-01", "1994-04-16", "1994-06-28", 
"1994-07-05", "1994-07-10", "1994-10-01", "1994-04-16", "1994-06-20", 
"1994-06-28", "1994-10-01", "1994-04-16", "1994-07-17", "1994-07-23", 
"1994-08-20", "1994-08-27", "1994-09-04", "1994-10-01", "1994-04-16", 
"1994-08-20", "1994-09-19", "1994-09-24", "1994-10-01", "1994-04-16", 
"1994-05-29", "1994-10-01", "1994-04-16", "1994-07-10", "1994-07-17", 
"1994-07-23", "1994-07-29", "1994-08-20", "1994-08-27", "1994-10-01", 
"1994-04-16", "1994-07-05", "1994-07-17", "1994-10-01", "1994-04-16", 
"1994-07-17", "1994-10-01", "1994-04-16", "1994-05-23", "1994-10-01", 
"1994-04-23", "1994-07-05", "1994-07-17", "1994-07-23", "1994-09-20", 
"1994-04-23", "1994-05-23", "1994-05-29", "1994-09-20"), NOM = structure(c(16L, 
16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 
16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 
16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 
16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 
16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 
16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 
16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 
16L, 16L, 16L, 16L, 16L, 16L, 16L, 16L), .Label = c("ANCIENNES CARRIERES D'ORIVAL", 
"BAIE DE L'AIGUILLON (VENDEE)", "CHERINE", "COMBE LAVAUX-JEAN ROLAND", 
"COTE DE MANCY", "Espace protégé - code", "ESTAGNOL", "GRAND PIERRE ET VITAIN", 
"ILE DE LA PLATIERE", "LAC DE REMORAY", "MARAIS DE LAVOURS", 
"PETITE CAMARGUE ALSACIENNE", "PINAIL", "RAMIERES DU VAL DE DROME", 
"RAVIN DE VALBOIS", "TOURBIERE DES DAUGES"), class = "factor"), 
SITE = structure(c(104L, 104L, 104L, 104L, 104L, 104L, 104L, 
104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 
104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 
104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 
104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 
104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 
104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 
104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 
104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 104L, 
104L, 104L, 104L, 104L, 105L, 105L, 105L, 105L, 105L, 105L, 
105L, 105L, 105L), .Label = c("Libellé du site", "RNN027-Estagnol 01", 
"RNN027-Estagnol 02", "RNN027-Estagnol 03", "RNN027-Estagnol 04", 
"RNN027-Estagnol 05", "RNN027-Estagnol 06", "RNN037-GPV 01", 
"RNN037-GPV 02", "RNN037-GPV 03", "RNN037-GPV 04", "RNN037-GPV 05", 
"RNN044-Pinail A", "RNN044-Pinail B", "RNN044-Pinail C", 
"RNN044-Pinail D", "RNN044-Pinail E", "RNN044-Pinail F", 
"RNN044-Pinail G", "RNN044-Pinail I", "RNN044-Pinail J", 
"RNN044-Pinail K", "RNN046-Remoray 01", "RNN046-Remoray 02", 
"RNN046-Remoray 03", "RNN046-Remoray 04", "RNN046-Remoray 05", 
"RNN046-Remoray 06", "RNN046-Remoray 07", "RNN046-Remoray 08", 
"RNN046-Remoray 09", "RNN046-Remoray 10", "RNN060-PCA Canal", 
"RNN060-PCA Heid", "RNN060-PCA Luzernière", "RNN060-PCA Mitlere-au", 
"RNN060-PCA Petite Heid", "RNN066-Valbois Ourlet bas", "RNN066-Valbois Ourlet haut", 
"RNN066-Valbois Pel Humbert", "RNN066-Valbois Pel Martin", 
"RNN066-Valbois Pel Podgo", "RNN066-Valbois Pel Podgo corniche", 
"RNN066-Valbois Pel temoin", "RNN066-Valbois Vignes parc2bas", 
"RNN066-Valbois Vignes parc2haut", "RNN066-Valbois Vignes parc3bas", 
"RNN066-Valbois Vignes parc3haut", "RNN068-Marais Lavours beon1", 
"RNN068-Marais Lavours beon2", "RNN068-Marais Lavours beon3", 
"RNN068-Marais Lavours beon4", "RNN068-Marais Lavours beon5", 
"RNN068-Marais Lavours ceyzerieu1", "RNN068-Marais Lavours culoz1", 
"RNN078-Chérine 01", "RNN078-Chérine 02", "RNN078-Chérine 03", 
"RNN078-Chérine 04", "RNN078-Chérine 05", "RNN078-Chérine 06", 
"RNN078-Chérine 07", "RNN078-Chérine 08", "RNN078-Chérine 09", 
"RNN078-Chérine 10", "RNN078-Chérine 11", "RNN078-Chérine 12", 
"RNN079-Platière 01LGRA01", "RNN079-Platière 01LGRA03", "RNN079-Platière 01LGRA04", 
"RNN079-Platière 01LGRA07", "RNN079-Platière 01LGRA08", "RNN079-Platière 01LGRA11", 
"RNN079-Platière 01LGRA12", "RNN079-Platière 01LPGO01", "RNN079-Platière 01LPGO02", 
"RNN079-Platière 01LPGO03", "RNN079-Platière 01LPGO04", "RNN079-Platière 01LPGO05", 
"RNN079-Platière 01LPGO06", "RNN079-Platière 01LPGO07", "RNN079-Platière 01LPOV01", 
"RNN079-Platière 01LPOV02", "RNN079-Platière 01LPOV03", "RNN079-Platière 01LPOV04", 
"RNN079-Platière 01LPOV05", "RNN079-Platière 01LPOV06", "RNN089-Ramières 24", 
"RNN089-Ramières 25", "RNN089-Ramières 26", "RNN089-Ramières 27", 
"RNN089-Ramières 35", "RNN089-Ramières 36", "RNN089-Ramières 37", 
"RNN089-Ramières 43", "RNN089-Ramières 46", "RNN089-Ramières 47", 
"RNN130-Baie Aiguillon Charron-Casiers-vase", "RNN130-Baie Aiguillon Charron-Mizottes-Chaînes", 
"RNN130-Baie Aiguillon Charron-Pd-Digue-mer", "RNN130-Baie Aiguillon Triaize-Mizottes", 
"RNN130-Baie Aiguillon Triaize-Pd-Digue-1", "RNN130-Baie Aiguillon Triaize-Pd-Digue-2", 
"RNN144-Dauges 01", "RNN144-Dauges 02", "RNN144-Dauges 03", 
"RNN144-Dauges 04", "RNN144-Dauges 05", "RNN144-Dauges 06", 
"RNN144-Dauges 07", "RNN144-Dauges 08", "RNN144-Dauges 09", 
"RNN144-Dauges 10", "RNN144-Dauges 11", "RNN144-Dauges 12", 
"RNN144-Dauges 13", "RNN144-Dauges 14", "RNN144-Dauges 15", 
"RNN157-Combe Lavaux 01 Sentier des crêtes", "RNN157-Combe Lavaux 02 Sentier des dalles", 
"RNN157-Combe Lavaux 03 Plain des Essoyottes partie humide", 
"RNN157-Combe Lavaux 04 Plain des Essoyottes partie sèches", 
"RNN157-Combe Lavaux 05 Pelouses de Fontenottes", "RNN157-Combe Lavaux 06 Friches parc de nuit", 
"RNN157-Combe Lavaux 07 Friches", "RNN157-Combe Lavaux 08 Friches ouverture ONF", 
"RNN157-Combe Lavaux 09 Haut du Champ Sement", "RNN157-Combe Lavaux 10 Bas du Champ Sement", 
"RNR117-TRMANCY 01", "RNR117-TRMANCY 02", "RNR117-TRMANCY 03", 
"RNR117-TRMANCY 04", "RNR117-TRMANCY 05", "RNR117-TRMANCY 06", 
"RNR189-RNR_TRACO_01", "RNR189-RNR_TRACO_02", "RNR189-RNR_TRACO_03", 
"RNR189-RNR_TRACO_04", "RNR189-RNR_TRACO_05", "RNR189-RNR_TRACO_06a", 
"RNR189-RNR_TRACO_06b", "RNR189-RNR_TRACO_07", "RNR189-RNR_TRACO_08", 
"RNR189-RNR_TRACO_09a", "RNR189-RNR_TRACO_09b", "RNR189-RNR_TRACO_10", 
"RNR189-RNR_TRACO_11", "RNR189-RNR_TRACO_12", "RNR189-RNR_TRACO_13", 
"RNR189-RNR_TRACO_14", "RNR189-RNR_TRACO_15"), class = "factor"), 
LONG = c(80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 
80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 
80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 
80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 
80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 
80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 
80, 80, 80, 80, 115, 115, 115, 115, 115, 115, 115, 115, 115
), SP = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 4L, 4L, 4L, 4L, 
4L, 5L, 5L, 5L, 10L, 10L, 10L, 12L, 12L, 12L, 20L, 20L, 20L, 
20L, 29L, 29L, 29L, 29L, 29L, 29L, 29L, 29L, 29L, 29L, 29L, 
31L, 31L, 31L, 31L, 33L, 33L, 33L, 43L, 43L, 43L, 43L, 43L, 
43L, 43L, 44L, 44L, 44L, 44L, 44L, 56L, 56L, 56L, 56L, 61L, 
61L, 61L, 61L, 61L, 61L, 61L, 62L, 62L, 62L, 62L, 62L, 69L, 
69L, 69L, 70L, 70L, 70L, 70L, 70L, 70L, 70L, 70L, 72L, 72L, 
72L, 72L, 73L, 73L, 73L, 75L, 75L, 75L, 4L, 4L, 4L, 4L, 4L, 
15L, 15L, 15L, 15L), .Label = c("Aglais urticae (Linnaeus, 1758)", 
"Anthocharis cardamines (Linnaeus, 1758)", "Apatura iris (Linnaeus, 1758)", 
"Aphantopus hyperantus (Linnaeus, 1758)", "Aporia crataegi (Linnaeus, 1758)", 
"Araschnia levana (Linnaeus, 1758)", "Argynnis aglaja (Linnaeus, 1758)", 
"Argynnis paphia (Linnaeus, 1758)", "Boloria dia (Linnaeus, 1767)", 
"Boloria euphrosyne (Linnaeus, 1758)", "Boloria selene (Denis & Schiffermüller, 1775)", 
"Brenthis daphne (Bergsträsser, 1780)", "Brintesia circe (Fabricius, 1775)", 
"Callophrys rubi (Linnaeus, 1758)", "Carterocephalus palaemon (Pallas, 1771)", 
"Celastrina argiolus (Linnaeus, 1758)", "Clossiana dia (Linnaeus, 1767)", 
"Clossiana selene (Denis & Schiffermüller, 1775)", "Coenonympha pamphilus (Linnaeus, 1758)", 
"Colias croceus (Fourcroy, 1785)", "Colias hyale (Linnaeus, 1758)", 
"Colias PC (hyale / alfacariensis) #complexe", "Cupido argiades (Pallas, 1771)", 
"Erebia meolans (de Prunner, 1798)", "Erynnis tages (Linnaeus, 1758)", 
"Euchloe PC (ausonia / simplonia) #complexe", "Euphydryas aurinia (Rottemburg, 1775)", 
"Everes argiades (Pallas, 1771)", "Gonepteryx rhamni (Linnaeus, 1758)", 
"Hesperia comma (Linnaeus, 1758)", "Heteropterus morpheus (Pallas, 1771)", 
"Hipparchia fagi (Scopoli, 1763)", "Inachis io (Linnaeus, 1758)", 
"Iphiclides podalirius (Linnaeus, 1758)", "Issoria lathonia (Linnaeus, 1758)", 
"Ladoga camilla (Linnaeus, 1764)", "Lampides boeticus (Linnaeus, 1767)", 
"Lasiommata megera (Linnaeus, 1767)", "Limenitis camilla (Linnaeus, 1764)", 
"Limenitis reducta Staudinger, 1901", "Lycaena phlaeas (Linnaeus, 1761)", 
"Lycaena tityrus (Poda, 1761)", "Maniola jurtina (Linnaeus, 1758)", 
"Melanargia galathea (Linnaeus, 1758)", "Melitaea cinxia (Linnaeus, 1758)", 
"Melitaea diamina (Lang, 1789)", "Melitaea didyma (Esper, 1778)", 
"Melitaea phoebe (Denis & Schiffermüller, 1775)", "Mellicta athalia (Rottemburg, 1775)", 
"Mellicta C (athalia / deione / parthenoides) #complexe", 
"Mellicta parthenoides (Keferstein, 1851)", "Mesoacidalia aglaja (Linnaeus, 1758)", 
"Nymphalis antiopa (Linnaeus, 1758)", "Nymphalis polychloros (Linnaeus, 1758)", 
"Ochlodes venatus (Bremer & Grey, 1853)", "Ochlodes venatus faunus (Turati, 1905)", 
"Papilio machaon Linnaeus, 1758", "Pararge aegeria (Linnaeus, 1758)", 
"Pieris 2 (rapae / mannii / napi) #complexe", "Pieris brassicae (Linnaeus, 1758)", 
"Pieris napi (Linnaeus, 1758)", "Pieris PC (rapae / mannii) #complexe", 
"Plebeius agestis (Denis & Schiffermüller, 1775)", "Plebejus argus (Linnaeus, 1758)", 
"Polygonia c-album (Linnaeus, 1758)", "Polyommatus icarus (Rottemburg, 1775)", 
"Polyommatus semiargus (Rottemburg, 1775)", "Pseudophilotes baton (Bergsträsser, 1779)", 
"Pyrgus 1 C (malvae / malvoides) #complexe", "Pyronia tithonus (Linnaeus, 1767)", 
"Quercusia quercus (Linnaeus, 1758)", "Thymelicus lineola (Ochsenheimer, 1808)", 
"Thymelicus sylvestris (Poda, 1761)", "Vanessa atalanta (Linnaeus, 1758)", 
"Vanessa cardui (Linnaeus, 1758)"), class = "factor"), SUMNB = c(0, 
2, 0, 0, 2, 0, 0, 12, 18, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 
0, 4, 2, 0, 0, 2, 2, 2, 2, 6, 2, 2, 4, 2, 0, 0, 2, 2, 0, 
0, 2, 0, 0, 2, 2, 2, 6, 6, 0, 0, 4, 4, 4, 0, 0, 4, 2, 0, 
0, 2, 2, 4, 2, 2, 0, 0, 4, 2, 2, 0, 0, 2, 0, 0, 2, 2, 6, 
4, 2, 4, 0, 0, 2, 2, 0, 0, 4, 0, 0, 2, 0, 0, 4, 6, 2, 0, 
0, 2, 2, 0), NB100 = c(0, 2.5, 0, 0, 2.5, 0, 0, 15, 22.5, 
2.5, 0, 0, 2.5, 0, 0, 2.5, 0, 0, 2.5, 0, 0, 5, 2.5, 0, 0, 
2.5, 2.5, 2.5, 2.5, 7.5, 2.5, 2.5, 5, 2.5, 0, 0, 2.5, 2.5, 
0, 0, 2.5, 0, 0, 2.5, 2.5, 2.5, 7.5, 7.5, 0, 0, 5, 5, 5, 
0, 0, 5, 2.5, 0, 0, 2.5, 2.5, 5, 2.5, 2.5, 0, 0, 5, 2.5, 
2.5, 0, 0, 2.5, 0, 0, 2.5, 2.5, 7.5, 5, 2.5, 5, 0, 0, 2.5, 
2.5, 0, 0, 5, 0, 0, 2.5, 0, 0, 3.47826086956522, 5.21739130434783, 
1.73913043478261, 0, 0, 1.73913043478261, 1.73913043478261, 
0)), .Names = c("YEAR", "RN", "DATE", "NOM", "SITE", "LONG", 
"SP", "SUMNB", "NB100"), class = c("data.table", "data.frame"
), row.names = c(NA, -100L), .internal.selfref = <pointer: 0x0000000000210788>)

1 个答案:

答案 0 :(得分:1)

也许您不是tapply而是ave(有关详细信息,请参阅?ave)。

我创建了一个简化的示例数据集:

## create example dataset
set.seed(1)
df <- data.frame(YEAR=rep(2001:2005, each=4), MONTH=rep(1:10, each=2),
                 DAY=rep(1:10, each=2),
                 VALUE=sample(1:20))

## turn YEAR, MONTH, DAY into factors
df <- within(df, {
  YEAR <- factor(YEAR)
  MONTH <- factor(MONTH)
  DAY <- factor(DAY)
})

## your function (simplified for my example)
your_function <- function(x) {
  as.numeric(c(NA, tail(x, -1)-head(x,-1)))
}

## run `your_function` for equal combinations of YEAR, MONTH, DAY
df$DIFF <- ave(df$VALUE, df$YEAR, df$MONTH, df$DAY, FUN=your_function)
df
#   YEAR MONTH DAY VALUE DIFF
#1  2001     1   1     6   NA
#2  2001     1   1     8    2
#3  2001     2   2    11   NA
#4  2001     2   2    16    5
#5  2002     3   3     4   NA
#6  2002     3   3    14   10
#7  2002     4   4    15   NA
#8  2002     4   4     9   -6
#9  2003     5   5    19   NA
#10 2003     5   5     1  -18
#11 2003     6   6     3   NA
#12 2003     6   6     2   -1
#13 2004     7   7    20   NA
#14 2004     7   7    10  -10
#15 2004     8   8     5   NA
#16 2004     8   8     7    2
#17 2005     9   9    12   NA
#18 2005     9   9    17    5
#19 2005    10  10    18   NA
#20 2005    10  10    13   -5

在你的例子中应该是:

DF$DIFF <- ave(DF$DATE, DF$SITE, DF$YEAR, DF$SP, FUN=function(x) {
   as.numeric(c(NA, as.Date(tail(x,-1)) - as.Date(head(x,-1)))))
}