【问题标题】:Multiple loops following string and subsets字符串和子集之后的多个循环
【发布时间】:2013-12-06 12:00:13
【问题描述】:

我目前被我的数据框困住了,我想知道如何做“子集子集的子集” 这是我的数据框的一部分:

    YEAR    RN      DATE    NAME            SITE           LONG SP                         SUMNB            NB100
1   2011    RNN027  15056   ESTAGNOL    RNN027-Estagnol 02  310 Anthocharis cardamines (Linnaeus, 1758) 1   0.3225806
2   2011    RNN027  15075   ESTAGNOL    RNN027-Estagnol 02  310 Anthocharis cardamines (Linnaeus, 1758) 1   0.3225806
3   2003    RNN027  12166   ESTAGNOL    RNN027-Estagnol 03  330 Anthocharis cardamines (Linnaeus, 1758) 2   0.6060606
4   2006    RNN027  13252   ESTAGNOL    RNN027-Estagnol 03  330 Anthocharis cardamines (Linnaeus, 1758) 2   0.6060606
5   2006    RNN027  13257   ESTAGNOL    RNN027-Estagnol 03  330 Anthocharis cardamines (Linnaeus, 1758) 2   0.6060606
6   2005    RNN027  12895   ESTAGNOL    RNN027-Estagnol 01  540 Anthocharis cardamines (Linnaeus, 1758) 2   0.3703704

我的意思是计算每个物种的丰度因子。为此,我必须隔离每个物种、每年和每个地点的每个计数日期。

我的第一个想法是做多个循环并按照之前的标准对每一步进行子集化:

DF --> 循环站点;每个站点的子集->循环年;每年的子集 --> 循环 SP;每个物种的子集--> 观察日期

隔离这些日期需要进一步修改(添加行),但我需要能够在之后重写修改后的子集并重建一个新的数据帧。

我构建了循环命令:

LOOPSITE<-sort(unique(DF$SITE))
for(i in LOOPSITE){
  print(i)
  LOOPSITESUB<-subset(DF,grepl(i,SITE))
  LOOPYEAR<-sort(unique(LOOPSITESUB$YEAR))
  print(LOOPYEAR)

  for(j in LOOPYEAR){
    print(j)
    LOOPYEARSUB<-subset(LOOPSITESUB,grepl(j,YEAR))
    LOOPSP<-sort(unique(LOOPYEARSUB$SP))
    print(length(LOOPSP))
       for(k in LOOPSP){
         print(k)
         LOOPSPSUB<-subset(LOOPYEARSUB,grepl(k,SP))
         print(sum(LOOPYEARSUB$SUMNB))
         print(head(LOOPSPSUB))
    }      
  }
}

我可以看出我的脚本正在使用所有这些“打印”命令,并且它一直在工作,直到我到达物种子集。由于未知原因,最后一个子集不涉及每个物种,而只是其中一些。以下是上一个站点和上一年的部分输出:

"RNN027-Estagnol 01"
...(I skipped all the sites)
"RNN027-Estagnol 06"
"2003"
...(I skipped all the years)
"2011"
[1] 22
[1] "Aricia agestis D., 1775"
[1] 107
   YEAR     RN       DATE      NOM               SITE LONG                      SP SUMNB     NB100
66 2011 RNN027 2011-04-21 ESTAGNOL RNN027-Estagnol 06  260 Aricia agestis D., 1775         1 0.3846154
67 2011 RNN027 2011-05-22 ESTAGNOL RNN027-Estagnol 06  260 Aricia agestis D., 1775     1 0.3846154
68 2011 RNN027 2011-08-05 ESTAGNOL RNN027-Estagnol 06  260 Aricia agestis D., 1775     2 0.7692308
[1] "Brintesia circe (Fabricius, 1775)"
[1] 107
[1] YEAR  RN    DATE  NOM   SITE  LONG  SP    SUMNB NB100
<0 rows> (or 0-length row.names)
[1] "Carcharodus alceae (Esper, 1780)"
[1] 107
[1] YEAR  RN    DATE  NOM   SITE  LONG  SP    SUMNB NB100
<0 rows> (or 0-length row.names)

它适用于“Aricia agetis D., 1775”,但不适用于“Brintesia circe (Fabricius, 1775)”。 我在我的数据框上验证了,在这个时间和地点观察到了第二个物种,并且具有与前一个相同的格式......它应该可以工作。

我可以这样堆叠多少个循环?还有另一种方法吗? (这会方便快捷)。我知道“拆分”功能,它基本上会分解每个组,但由于我不能利用每个“块”,它不适合我的任务。我可能错了。

在最后一步(修改所有子集之后),我应该能够将每个子集写入一个新的数据帧,以重建我输入的修改版本。

我可能走错了路! 如果需要,我可以提供进一步的解释!

感谢您的帮助!

编辑:

我会尝试解释我想要做什么。 为了计算我的丰度指数,我需要在每个时间“会话”的观察之前和之后添加“空白”行。基本上,我尝试为 3 个不同因素(SITE、YEAR 和 SP)的每种组合获取一个子集。

这是我想要获得的输出类型的示例。 对于每个 SITE X/YEAR Y/SP Z 可能的组合:

 YEAR    RN      DATE    NAME            SITE           LONG SP  SUMNB NB100
----ADD A NEW ROW----DATE MINUS 7 DAYS-----------------------------------------------------------------------------------
1   Y    RNN027  15056   ESTAGNOL    RNN027-Estagnol X  310 SP Z  1   0.3225806
2   Y    RNN027  15075   ESTAGNOL    RNN027-Estagnol X  310 SP Z  1   0.3225806
3   Y    RNN027  12166   ESTAGNOL    RNN027-Estagnol X  330 SP Z  2   0.6060606
4   Y    RNN027  13252   ESTAGNOL    RNN027-Estagnol X  330 SP Z  2   0.6060606
5   Y    RNN027  13257   ESTAGNOL    RNN027-Estagnol X  330 SP Z  2   0.6060606
6   Y    RNN027  12895   ESTAGNOL    RNN027-Estagnol X  540 SP Z  2   0.3703704
----ADD A NEW ROW----DATE PLUS 7 DAYS-----------------------------------------------------------------------------------

然后我在新的 DF 中重写和编译每个修改的子集。

编辑 2: 除非我删除了未使用的值,否则使用“split(DF, list(DF$SITE, DF$YEAR, DF$SP))”会使我的计算机崩溃。我得到了我想要的,但是如何访问和修改每个子集?

【问题讨论】:

  • 能否将dput(head(DF)) 的输出添加到您的问题中?
  • 如果我对您的理解正确,您似乎想要“计算每个群体的某些东西”——每个物种、地点和年份的丰度。如果是这样,您可能会查看herehere 的一些想法。以及关于这个主题的大量帖子。干杯。
  • 现在,我不想计算任何东西。为了在不低估任何东西的情况下计算我的索引,我需要在每个子集之前和之后添加一行。这些行的日期设置在第一个日期之前和最后一个观察日期之后的 7 天。如果我理解您的第一个链接(SO)中所说的内容,我可以使用“tapply”应用该功能,但仅适用于一个因素吗?
  • 老实说我不清楚你想要什么,但这有什么用:split(DF, list(DF$SITE, DF$YEAR, DF$SP), sep = " _ ")lapply(split(DF, list(DF$SITE, DF$YEAR, DF$SP), sep = " _ "), function(x) x$DATE)?也许您可以添加所需的输出?

标签: r


【解决方案1】:

我想你正在寻找aggregate

aggregate(SUMNB ~ SITE + YEAR + SP, DF, sum)

#                 SITE YEAR                                      SP SUMNB
# 1 RNN027-Estagnol 03 2003 Anthocharis cardamines (Linnaeus, 1758)     2
# 2 RNN027-Estagnol 01 2005 Anthocharis cardamines (Linnaeus, 1758)     2
# 3 RNN027-Estagnol 03 2006 Anthocharis cardamines (Linnaeus, 1758)     4
# 4 RNN027-Estagnol 02 2011 Anthocharis cardamines (Linnaeus, 1758)     2

该命令针对SITEYEARSP 的每个组合计算SUMNB 中所有值的总和。


编辑

以下代码是否会产生您正在寻找的内容?

do.call(rbind, by(DF, DF[c("SITE", "YEAR", "SP")], FUN = function(x) {
  tmp <- x[c(1, seq(nrow(x)), nrow(x)), ]
  tmp$DATE[1] < tmp$DATE[1] - 7
  tmp$DATE[nrow(tmp)] <- tmp$DATE[nrow(tmp)] + 7
  return(tmp)
}))

【讨论】:

  • 为了构建我的输入 DF,我已经进行了聚合。正如其他答案的 cmets 中所解释的,我需要在每个“块”之前和之后添加行。聚合不允许我这样做。
  • @user2542995 您希望在其他行的其他列中使用哪些值?
  • 是的,它正在工作!我能够根据需要将 SUMNB 和 NB100 的值设置为零。非常感谢!
【解决方案2】:

根据您的编辑,我相信这可能有用:

set.seed(11)
DF <- data.frame(YEAR = sample(c(2001, 2003), 5, T),     #random data
                 SITE = sample(c("a", "b"), 5, T),
                 SP = sample(c("sp1", "sp2"), 5, T),
                 DATE = sample(12345:15678, 5))

res <- lapply(split(DF, list(DF$SITE, DF$YEAR, DF$SP)), 
                function(x) 
                {
                 if(nrow(x) > 0)
                  {
                   row1 <- x[1,]
                   names(row1) <- colnames(x)
                   row1["DATE"] <- x$DATE[1] - 7

                   rown <- x[nrow(x),]
                   names(rown) <- colnames(x)
                   rown["DATE"] <- x$DATE[nrow(x)] + 7

                   rbind(row1, x, rown)
                  } 
                })
DF2 <- do.call(rbind, res)
rownames(DF2) = seq_len(nrow(DF2))

DF
#  YEAR SITE  SP  DATE
#1 2001    b sp1 14257
#2 2001    a sp1 13950
#3 2003    a sp2 13446
#4 2001    b sp2 12870
#5 2001    a sp2 13943
DF2
#   YEAR SITE  SP  DATE
#1  2001    a sp1 13943
#2  2001    a sp1 13950
#3  2001    a sp1 13957
#4  2001    b sp1 14250
#5  2001    b sp1 14257
#6  2001    b sp1 14264
#7  2001    a sp2 13936
#8  2001    a sp2 13943
#9  2001    a sp2 13950
#10 2001    b sp2 12863
#11 2001    b sp2 12870
#12 2001    b sp2 12877
#13 2003    a sp2 13439
#14 2003    a sp2 13446
#15 2003    a sp2 13453

【讨论】:

  • 我的 DF 太重了,这个命令在我的电脑上花费了太多时间。但是,它仍然有效!谢谢!
猜你喜欢
  • 2015-09-07
  • 1970-01-01
  • 2015-06-06
  • 1970-01-01
  • 2020-01-10
  • 2014-11-24
  • 2021-01-28
  • 2014-08-05
  • 1970-01-01
相关资源
最近更新 更多