Как определить новые столбцы с несколькими критериями в [R] (для цикла внутри ddply) - PullRequest
0 голосов
/ 28 февраля 2012

Мне трудно понять, как именно решить эту проблему, и я надеюсь, что у кого-то есть идея. Для следующего кода я хочу получить результат, приведенный ниже. Результат основан на следующих критериях:

В тот же день:
idEffectA:
Всегда 0 для строк с идентификатором A
1 для строк «без идентификатора A», если есть какой-либо идентификатор. Строка с 1 в специальном значении для этой даты
0 для строк «без идентификатора A», если все строки идентификатора A имеют специальное значение 0 для этой даты

sizeEffect10:
Всегда 0 для рядов размером 10
1 для строк "не размера 10", если есть какая-либо строка размера 10 с символом 1 для этой даты
0 для строк "не размера 10", если все размеры 10 имеют специальное значение 0 для этой даты

Аналогично для других переменных. Если бы имена столбцов также могли быть сгенерированы, это было бы чрезвычайно полезно, вместо того, чтобы определять каждое вручную. Кроме того, в фактическом наборе данных есть много разных категорий для размера и идентификатора, поэтому было бы лучше избегать ручного ввода их в функцию, хотя, если это единственная возможность, агрегатная функция, используемая с объединением, могла бы использоваться в данных установить с определенной функцией (какие-либо другие предложения?). Я хотел бы, чтобы столбцы результата были связаны с исходным набором данных.

Пожалуйста, дайте мне знать, если есть какие-либо вопросы, так как мне было трудно определить, что я хотел в столбцах для начала. Я пытался использовать пакет 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
}

То, что я надеялся сделать с этим кодом, это создать 0 для всех идентификаторов, как я написал в оригинальном сообщении:

idEffectA:
Всегда 0 для строк с идентификатором A

и создайте столбец для каждого отдельного идентификатора. Тем не менее, я не знаю, что делать с другими условиями или как их вписать. Стоит ли добавлять вложенные операторы ifelse? Любая помощь с благодарностью. Я более привык работать с индексированием в R, поэтому мои знания ifelse и for являются нечеткими. Спасибо.

1 Ответ

2 голосов
/ 29 февраля 2012

Во-первых, приведите данные в воспроизводимую форму (я использовал dput() на original.data, что я прочитал из того, что у вас было, и сделал некоторые преобразования). Это гарантирует, что все типы данных являются правильными (date имеет тип Date, а id - это factor и т. Д .; эти вещи актуальны.)

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")

Вы хотите ddply (data.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
})

Для idEffectA, others проверяет, являются ли какие-либо из значений special, соответствующих значению A, 1 и равны 1, если это так, 0 в противном случае. Тогда присвоение idEffectA зависит от того, является ли оно A (0) или нет (каким бы ни было others). Повторите логику для размера, но сравнивая с числом.

Ваш дальнейший пример показывает, что вы хотите столбец для каждого возможного значения id и size. Петли могут доставить вас туда.

allid <- 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 и size (allid и allsize), поскольку это нужно сделать только один раз. Внутри функции для каждой даты выполните итерации по каждому возможному значению id. Постройте столбцы «Эффект» таким же образом, но с помощью paste создайте имя столбца.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...