根据其他列中的值对数据框列进行条件更改

时间:2014-01-05 18:17:19

标签: r dataframe

在模拟数据集中

n =  50
set.seed(378)
df <- data.frame(
  age = sample(c(20:90), n, rep = T), 
  sex = sample(c("m", "f"), n, rep = T, prob = c(0.55, 0.45)),
  smoker = sample(c("never", "former", "active"), n, rep = T, prob = c(0.4, 0.45, 0.15)), 
  py = abs(rnorm(n, 25, 10)),
  yrsquit = abs (rnorm (n, 10,2)),
  outcome = as.factor(sample(c(0, 1), n, rep = T, prob = c(0.8, 0.2)))
  )

我需要在结果组之间引入一些不平衡(1 =疾病,0 =无疾病)。例如,患有该疾病的受试者年龄较大且更可能是男性。我试过了

df1 <- within(df, sapply(length(outcome), function(x) {
if (outcome[x] == 1)  {
  age[x] <- age[x] + 15
  sex[x] <- sample(c("m","f"), prob=c(0.8,0.2))
}
}))

显示没有区别
tapply(df$sex, df$outcome, length)
tapply(df1$sex, df$outcome, length)
tapply(df$age, df$outcome, mean)
tapply(df1$age, df$outcome, mean)

1 个答案:

答案 0 :(得分:2)

sapply内使用within并不像您预期​​的那样有效。函数within仅使用返回的sapply值。但是在您的代码中,sapply会返回NULL。因此,within不会修改数据框。

这是一种更简单的方法来修改数据框而没有循环或sapply

idx <- df$outcome == "1"
df1 <- within(df, {age[idx] <- age[idx] + 15; 
                   sex[idx] <- sample(c("m", "f"), sum(idx), 
                                      replace = TRUE, prob = c(0.8, 0.2))})

现在,数据框架不同了:

> tapply(df$age, df$outcome, mean)
       0        1 
60.46341 57.55556 
> tapply(df1$age, df$outcome, mean)
       0        1 
60.46341 72.55556 

> tapply(df$sex, df$outcome, summary)
$`0`
 f  m 
24 17 

$`1`
f m 
2 7 

> tapply(df1$sex, df$outcome, summary)
$`0`
 f  m 
24 17 

$`1`
f m 
1 8