【问题标题】:Identifying groups of individuals if conditional occurence in one of them如果其中一个有条件地出现,则识别个体群体
【发布时间】:2017-05-11 23:03:03
【问题描述】:

我正在尝试从数据库中识别(使用二进制 1/0 变量)主题组,只要该组中至少有一个主题满足两个条件。

我的数据库DF由描述每个成员的性别和年龄的家庭组成(以及家庭 ID family):我想创建一个新的二进制变量NoMan,如果至少为 0一个家庭的男性(sx 属性为1)的年龄超过 16 岁,否则将取值 1。请注意,我希望 NoMan 与来自同一家庭的所有成员。

family <- factor(rep(c("001","002","003"), c(10,8,15)),
                 levels=c("001","002","003"), labels=c("001","002","003"), ordered=TRUE)
ag <- c(22,8,4,2,55,9,44,65,1,7,32,2,2,1,6,9,18,99,73,1,2,3,4,5,6,7,8,9,10,18,11,22,33)
sx <- c(1,2,2,2,1,2,2,2,1,1,2,1,2,1,2,1,2,2,2,2,1,2,1,2,1,2,1,2,1,2,1,2,2)
DF <- data.frame(family, ag, sx)
DF

我曾尝试将ddplyifelse结合使用,但这并不成功:

DF <- ddply(DF,.(family), transform, NoMan=ifelse(sx==1 & ag>16, 1, 0))
DF

似乎除了最终的其他限制之外,在此脚本中,函数适用于个人而不是家庭(我实际上希望他们将相同的结果应用于同一家庭的所有成员)。

我觉得我在正确的轨道上,但也许有人对这个问题有很好的解决方案?

PS:刚刚编辑了DF,因为在这个例子中我希望家庭003的所有成员都被标记为NoMan==1

【问题讨论】:

  • 谢谢 Uwe Block
  • 因为你已经改变了 Q,我猜所有的答案——尤其是 S van Balen 接受的答案——也应该被修改。
  • 确实是Uwe Block,我的错……年龄条件应该都是ag&gt;16。大多数答案在这里都很好用。谢谢

标签: r conditional plyr


【解决方案1】:
    DF$NoMan = c(! DF$family %in% unique(DF[DF$sx == 1 & DF$ag < 16,1]))

【讨论】:

  • 我喜欢 em 在一行中;)另外,这可以为您节省一个图书馆,物有所值。
【解决方案2】:

ifelse 返回一个结果向量,忽略组,您可以使用any 聚合每个组的结果:

library(plyr)
ddply(DF, .(family), transform, NoMan = +any(sx == 1 & ag < 16))

【讨论】:

  • 谢谢,但是使用这个我刚刚将1 作为NoMan 的值:我们是否应该像ifelse 那样指定条件的结果?前任。什么时候取值 0,什么时候取值 1?谢谢!
  • 这取决于您希望您的数据如何。此逻辑基于二进制变量 NoMan,如果一个家庭中的至少一个男性(属性为 1 的 sx)小于 16 岁,则该变量为 0。当然,对于您的样本数据,所有家庭都包含至少一名年龄小于 16 岁的男性。您的描述与您的代码不同。也许你想要ddply(DF, .(family), transform, NoMan = +!any(sx == 1 &amp; ag &lt; 16))
  • 对不起!你是对的,我已经在数据中更改了这个,现在应该可以使用新的DF? .. 但我仍然只得到 1 作为输出(或你上一个脚本中的 0)。
  • 数据仍然包含三个家庭,每个家庭至少有一个男性且年龄
  • 再次抱歉,您的解决方案工作正常,但我提出问题时没有足够小心:每当一名男性年龄超过 16 岁时,我都想要值“1”! DF &lt;- ddply(DF, .(family), transform, NoMan = +!any(sx == 1 &amp; ag &gt; 16)) ; DF
【解决方案3】:

我们可以使用dplyr

library(dplyr)
DF %>%
   group_by(family) %>% 
   mutate(NoMan = as.integer(any(sx == 1 & ag < 16)))

或者使用来自base Rave

DF$NoMan <- with(DF, as.integer(ave(sx==1 & ag < 16, family, FUN = any)))

【讨论】:

  • 谢谢,但是当我尝试时,这个第一个解决方案不起作用。您的第二个解决方案工作正常,但二进制变量值被反转(0 而不是 1,反之亦然)。
  • @den 我使用了dplyr_0.5.0,它对我有用。关于第二种解决方案,如果您需要相反的解决方案,只需执行with(DF, as.integer(!ave(sx==1 &amp; ag &lt; 16, family, FUN = any))) 或更改条件
  • 太棒了! DF$NoMan &lt;- with(DF, as.integer(!ave(sx==1 &amp; ag &gt; 16, family, FUN = any))) 工作正常
【解决方案4】:
#Obtain unique families
family = c(unique(as.character(DF$family)))
NoMan  = c()

for (i in 1:length(family)){
#Subset a new dataframe for each family with only male members and check if minimun age is below 16
if (min(subset(DF,DF$family == family[1] & DF$sx=="1")$ag) < 16){
NoMan[i] = 1
} else {
NoMan[i] = 0
}
}

#Join unique family and NoMan into new dataframe
DF2 = cbind(family,NoMan)

#Use lookup command of qdapTools package
library(qdapTools)
DF$NoMan = lookup(DF$family,DF2)

【讨论】:

    猜你喜欢
    • 2017-05-18
    • 1970-01-01
    • 2018-08-14
    • 1970-01-01
    • 1970-01-01
    • 2023-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多