如何在[R]中定义具有多个条件的新列(对于ddply中的循环)

时间:2012-02-28 14:47:28

标签: r function

我无法弄清楚如何解决这个问题,并希望有人有个主意。对于以下代码,我想要下面给出的结果。结果基于以下标准:

在同一天内:
idEffectA:
对于ID为A的行,始终为0 1如果有任何id,则为“非id A”行。该行的特殊行为1 0表示“非id A”行,如果所有id A行在该日期的特殊值为0

sizeEffect10:
对于大小为10的行,始终为0 1表示“非大小10”行,如果有任何大小10行,其中1为特殊日期 0表示“非大小10”行,如果所有大小10都具有该日期的特殊值

同样适用于其他变量。如果也可以生成列的名称,那将非常有用,而不必手动定义每个列。此外,在实际数据集中,大小和id有许多不同的类别,因此避免将这些类型输入到函数中是最好的,但如果这是唯一的可能性,则可以在数据上使用与合并一起使用的聚合函数使用已定义的函数设置(任何其他建议?)。我希望结果列绑定到原始数​​据集。

如果有任何问题,请告诉我,因为我很难在列中开始实际定义我想要的内容。我已经尝试使用plyr包以及索引,但还没有走得太远。谢谢!

对于第一部分,我认为这样的事情可以在循环中起作用:

i=0  
ifelse(id==A & max(special[id=="A" & date==min(date)+i], 1, 0)  
i=i+7  

但是,之后我不确定......

     original.data
     label  date    special size    id
     1  1/11/2012   0   10  A
     2  1/11/2012   1   20  A
     3  1/11/2012   0   10  B
     4  1/11/2012   0   30  C
     5  1/11/2012   0   10  C
     1  1/18/2012   0   10  A
     2  1/18/2012   0   20  A
     3  1/18/2012   0   10  B
     4  1/18/2012   1   30  C
     5  1/18/2012   1   10  C
     1  1/25/2012   1   10  A
     2  1/25/2012   1   20  A
     3  1/25/2012   0   10  B
     4  1/25/2012   1   30  C
     5  1/25/2012   1   10  C
     1  2/1/2012    0   10  A
     2  2/1/2012    1   20  A
     3  2/1/2012    1   10  B
     4  2/1/2012    0   30  C
     5  2/1/2012    0   10  C
     1  2/8/2012    0   10  A
     2  2/8/2012    0   20  A
     3  2/8/2012    0   10  B
     4  2/8/2012    1   30  C
     5  2/8/2012    0   10  C
     1  2/15/2012   1   10  A
     2  2/15/2012   1   20  A
     3  2/15/2012   0   10  B
     4  2/15/2012   1   30  C
     5  2/15/2012   0   10  C

以下是我要找的结果:

     results
     idEffectA  sizeEffect10    idEffectB   sizeEffect20    idEffectC   sizeEffect30
     0  0   0   1   0   0
     0  0   0   0   0   0
     1  0   0   1   0   0
     1  0   0   1   0   0
     1  0   0   1   0   0
     0  0   0   0   1   1
     0  1   0   0   1   1
     0  0   0   0   1   1
     0  1   0   0   0   0
     0  0   0   0   0   1
     0  0   0   1   1   1
     0  1   0   0   1   1
     1  0   0   1   1   1
     1  1   0   1   0   0
     1  0   0   1   0   1
     0  0   1   1   0   0
     0  1   1   0   0   0
     1  0   0   1   0   0
     1  1   1   1   0   0
     1  0   1   1   0   0
     0  0   0   0   1   1
     0  0   0   0   1   1
     0  0   0   0   1   1
     0  0   0   0   0   0
     0  0   0   0   0   1
     0  0   0   1   1   1
     0  1   0   0   1   1
     1  0   0   1   1   1
     1  1   0   1   0   0
     1  0   0   1   0   1

好的,这是我的开始:

x <- rep(0, length(id)) 
i=min(date) 
n=1 
id.level = 1 

for(i in min(date):max(date)){
    for(id.level in 1:length(levels(id))){
        for(n in 1:length(id)){
            x[n] <- ifelse(max(special[id==id[id.level] & date==i])==1, 0, 1)
            n=n+1
        }
        y <- paste("idEffect",id[id.level]) 
        id.level = id.level + 1
        colnames(x)[length(colnames(x))] <- y
    }
    i=i+7
}

我希望用这个代码做的是创建所有id的0,就像我在原帖中写的那样:

idEffectA:
对于ID为

的行,始终为0

并为每个单独的ID创建一列。但是,我不知道如何处理其他条件或如何使它们适合。我应该添加嵌套的ifelse语句吗?任何帮助非常感谢。我更习惯于在R中使用索引,所以我对ifelse和语句的了解是模糊的。感谢。

1 个答案:

答案 0 :(得分:2)

首先,将数据转换为可重现的格式(我在dput()上使用了original.data,我从您所拥有的内容中读取并进行了一些转换)。这可以确保所有数据类型都正确(date类型为Dateidfactor等等;这些都是相关的。)

original.data <-
structure(list(label = c(1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 
5L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 
1L, 2L, 3L, 4L, 5L), date = structure(c(15350, 15350, 15350, 
15350, 15350, 15357, 15357, 15357, 15357, 15357, 15364, 15364, 
15364, 15364, 15364, 15371, 15371, 15371, 15371, 15371, 15378, 
15378, 15378, 15378, 15378, 15385, 15385, 15385, 15385, 15385
), class = "Date"), special = c(0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 
1L, 1L, 1L, 1L, 0L, 1L, 1L, 0L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 1L, 
0L, 1L, 1L, 0L, 1L, 0L), size = c(10L, 20L, 10L, 30L, 10L, 10L, 
20L, 10L, 30L, 10L, 10L, 20L, 10L, 30L, 10L, 10L, 20L, 10L, 30L, 
10L, 10L, 20L, 10L, 30L, 10L, 10L, 20L, 10L, 30L, 10L), id = structure(c(1L, 
1L, 2L, 3L, 3L, 1L, 1L, 2L, 3L, 3L, 1L, 1L, 2L, 3L, 3L, 1L, 1L, 
2L, 3L, 3L, 1L, 1L, 2L, 3L, 3L, 1L, 1L, 2L, 3L, 3L), .Label = c("A", 
"B", "C"), class = "factor")), .Names = c("label", "date", "special", 
"size", "id"), row.names = c(NA, -30L), class = "data.frame")

接下来,您要处理“在同一天内”。这意味着分裂 - 应用 - 组合策略。 plyr库可以很好地处理这个问题。

library("plyr")

您希望ddplydata.frame in,data.frame out),您需要一个函数来对与单个日期对应的数据子集进行转换。

使用前两个示例(idEffectA和sizeEffect10),实现规则如下:

ddply(original.data, .(date), function(DF) {
    # idEffectA
    others <- if(any(DF$special[DF$id == "A"] == 1)) {1} else {0}
    DF$idEffectA <- ifelse(DF$id == "A", 0, others)
    # sizeEffect10
    others <- if(any(DF$special[DF$size == 10] == 1)) {1} else {0}
    DF$sizeEffect10 <- ifelse(DF$size == 10, 0, others)
    DF
})

对于idEffectAothers会检查对应于special值的任何A值是否为1,且1是否为0如果是这样,idEffectA否则。然后,对A的分配取决于它是0others)还是不id被确定为。重复大小的逻辑,但与数字比较。

您的进一步示例表明您希望为sizeallid <- levels(original.data$id) allsize <- unique(original.data$size) ddply(original.data, .(date), function(DF) { for (e in allid) { others <- if(any(DF$special[DF$id == e] == 1)) {1} else {0} DF[[paste("idEffect",e,sep="")]] <- ifelse(DF$id == e, 0, others) } for (e in allsize) { others <- if(any(DF$special[DF$size == e] == 1)) {1} else {0} DF[[paste("sizeEffect",e,sep="")]] <- ifelse(DF$size == e, 0, others) } DF }) 的每个可能值添加一列。循环可以帮助你。

   label       date special size id idEffectA idEffectB idEffectC sizeEffect10 sizeEffect20 sizeEffect30
1      1 2012-01-11       0   10  A         0         0         0            0            1            0
2      2 2012-01-11       1   20  A         0         0         0            0            0            0
3      3 2012-01-11       0   10  B         1         0         0            0            1            0
4      4 2012-01-11       0   30  C         1         0         0            0            1            0
5      5 2012-01-11       0   10  C         1         0         0            0            1            0
6      1 2012-01-18       0   10  A         0         0         1            0            0            1
7      2 2012-01-18       0   20  A         0         0         1            1            0            1
8      3 2012-01-18       0   10  B         0         0         1            0            0            1
9      4 2012-01-18       1   30  C         0         0         0            1            0            0
10     5 2012-01-18       1   10  C         0         0         0            0            0            1
11     1 2012-01-25       1   10  A         0         0         1            0            1            1
12     2 2012-01-25       1   20  A         0         0         1            1            0            1
13     3 2012-01-25       0   10  B         1         0         1            0            1            1
14     4 2012-01-25       1   30  C         1         0         0            1            1            0
15     5 2012-01-25       1   10  C         1         0         0            0            1            1
16     1 2012-02-01       0   10  A         0         1         0            0            1            0
17     2 2012-02-01       1   20  A         0         1         0            1            0            0
18     3 2012-02-01       1   10  B         1         0         0            0            1            0
19     4 2012-02-01       0   30  C         1         1         0            1            1            0
20     5 2012-02-01       0   10  C         1         1         0            0            1            0
21     1 2012-02-08       0   10  A         0         0         1            0            0            1
22     2 2012-02-08       0   20  A         0         0         1            0            0            1
23     3 2012-02-08       0   10  B         0         0         1            0            0            1
24     4 2012-02-08       1   30  C         0         0         0            0            0            0
25     5 2012-02-08       0   10  C         0         0         0            0            0            1
26     1 2012-02-15       1   10  A         0         0         1            0            1            1
27     2 2012-02-15       1   20  A         0         0         1            1            0            1
28     3 2012-02-15       0   10  B         1         0         1            0            1            1
29     4 2012-02-15       1   30  C         1         0         0            1            1            0
30     5 2012-02-15       0   10  C         1         0         0            0            1            1

给出了

id

我预先计算sizeallidallsizeid)的可能值,因为只需要执行一次。在每个日期的函数内,迭代paste的每个可能值。以相同的方式构建“效果”列,但使用{{1}}创建列名称。