如何将负值转换为虚拟变量?

时间:2016-08-24 12:49:18

标签: r function dataframe

我想创建两个虚拟变量: a)一个捕获x1中所有负面变化的虚拟变量。如果有负变化== 1,否则== 0。

b)捕获所有-1(和更高)的更改。例如:10.5到9.5或10到9(或10到6)。这也是假的:如果-1或更多改变则== 1,否则== 0。

正确的数据看起来像这样,变量应捕获每个personID的负值。

   personid  year   x1
    33       1990    0
    33       1991    3.5
    33       1992    2.75
    33       1993    3.25
    33       1994    6
    34       1990    17
    34       1991    9
    34       1992    16.5
    34       1993    16.75

要进行复制,请使用以下代码。

set.seed(100)
mydata <- data.frame(
  x1    = sample(c(0:30, 1.5,5.75,9.25,10.25,11.75), 100, replace = TRUE),
  personID  = rep(c(1:10), each = 10)
  )

我尝试使用ave生成这些变量...它没有多大帮助。我知道我没有正确使用它但不确定在哪里..

mydata$a <- with(mydata, ave(x1, personID, FUN = function(x) c(TRUE, diff(x) !=-1) & x!=-1))

编辑:

dput(data)
structure(list(personid = c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 20L, 20L, 20L, 20L, 20L, 20L, 
20L, 20L, 20L, 20L, 20L, 20L, 20L, 20L, 20L, 20L, 20L, 40L, 40L, 
40L, 40L, 40L, 40L, 40L, 40L, 40L, 40L, 40L, 40L, 40L, 40L, 40L, 
40L, 40L, 41L, 41L, 41L, 41L, 41L, 41L, 41L, 41L, 41L, 41L, 41L, 
41L, 41L, 41L, 41L, 41L, 41L, 42L, 42L, 42L, 42L, 42L, 42L, 42L, 
42L, 42L, 42L, 42L, 42L, 42L, 42L, 42L, 42L, 42L, 51L, 51L, 51L, 
51L, 51L, 51L, 51L, 51L, 51L, 51L, 51L, 51L, 51L, 51L, 51L, 51L, 
51L), x1 = c(37, 34, 30.75, 29, 37, 32.25, 25.75, 32.5, 27, 31, 
28.5, 23.75, 25.75, 28.5, 28.5, 27.75, 25.75, 25.75, 27.25, 31, 
32.5, 35.5, 27.25, 32.25, 30.5, 28.75, 29.5, 29, 29, 27, 28.75, 
28.75, 25.75, 25.75, 22, 22, 29, 30, 20, 22, 12, 11.5, 10, 14.5, 
24, 15.5, 23.5, 14, 24, 10, 9, 34, 16, 9.5, 19, 31, 20, 9.5, 
9.5, 21, 29, 20, 26, 26, 24.5, 5, 16.5, 18.5, 22.5, 31.5, 23.5, 
20, 15.25, 20.75, 32, 23.5, 25, 20, 27, 22.5, 24.5, 28.5, 18, 
17.5, 18.5, 34, 30.5, 32.5, 31, 27, 31, 31, 35.5, 31, 31, 29, 
31.5, 29.25, 31, 31, 28, 29)), .Names = c("personid", "x1"), class = "data.frame", row.names = c(NA, 
-102L))

2 个答案:

答案 0 :(得分:2)

您正在寻找的是(1)一些拆分 - 应用 - 合并方法(weak在基础R中,tapplyddply中的组合} {,plyr + group_by mutate ...和(2)plyr

数据:

diff

您必须决定对每个人的序列中的第一个/最后一个值做什么:是(第一个,最后一个)等于(NA,0)的值?这里我将第一个值设置为零。

set.seed(100)
mydata <- data.frame(
  x1    = sample(c(0:30, 1.5,5.75,9.25,10.25,11.75), 100, replace = TRUE),
  personID  = rep(c(1:10), each = 10)
)

现在diff_to_dummy <- function(x) { c(0,as.numeric(diff(x) <(-1))) } 会将tapply的功能应用于每个x1; personID将值重新组合在一起。

unlist

答案 1 :(得分:0)

您还可以使用dplyr

library(dplyr)

result <- mydata %>% group_by(personID) %>%
                     mutate(a = ifelse((x1-lag(x1)) < 0, 1, 0)) %>%
                     mutate(b = ifelse((x1-lag(x1)) <= -1, 1, 0))

在此,我们检测到每个group_by的更改personID。函数mutate创建虚拟变量列ab。不使用diff,而是从lag(x1)中减去x1进行测试。使用seed=100模拟数据的结果,除了我将x1替换为行10.5中的2,以说明a1b0

print(result)
##Source: local data frame [100 x 4]
##Groups: personID [10]

##      x1 personID     a     b
##   <dbl>    <int> <dbl> <dbl>
##1     11        1    NA    NA
##2   10.5        1     1     0
##3     19        1     0     0
##4      2        1     1     1
##5     16        1     0     0
##6     17        1     0     0
##7     29        1     0     0
##8     13        1     1     1
##9     19        1     0     0
##10     6        1     1     1

或者,我们可以使用diff来测试条件,但是我们需要在NA前面添加结果,以便mutate使用的函数返回的结果相同输入的长度:

result <- data %>% group_by(personid) %>%
                   mutate(a = c(NA, ifelse(diff(x1) < 0, 1, 0))) %>%
                   mutate(b = c(NA, ifelse(diff(x1) <= -1, 1, 0)))