我有一个df,其中我的观察结果按ID分组。
我不想创建两个假人,都在组级别上(在同一ID内)。
我的df的一个例子是:
ID | 少数 | 判决 |
---|---|---|
1 | 10 | |
1 | 0 | 5 |
1 | 0 | 5 |
2 | 0 | 20 |
2 | 1 | 15 |
2 | 0 | 20 |
以下是不起作用的:
mutate(stricter = ifelse(minority == 1 & sentencing > sentencing & minority == 0))
# ^^^ ^^^^
对CCD_ 1的两个引用都是向量,并将self与self进行比较。不同的是,它实际上是
dat$sentencing[1:3]
# [1] 10 5 5
dat$sentencing[1:3] > dat$sentencing[1:3]
# [1] FALSE FALSE FALSE
c(10, 5, 5) > c(10, 5, 5)
# [1] FALSE FALSE FALSE
我认为你的意思是沿着">该CCD_ 2与所有其它CCD_,这不能以矢量化的方式直接完成。有几种方法可以解决这个问题,包括outer(..)
,但我认为最容易可视化的可能是sapply(sentencing, function(sen) ...)
,在函数内部,sen
指的是每个单独的值,sentencing
指的是(组内)值的整个向量。
尝试
dat %>%
group_by(ID) %>%
mutate(
stricter = if (all(0:1 %in% minority)) +(minority == 1 & sapply(sentencing, function(sen) any(sen > sentencing[minority == 0]))) else 0L,
lenient = if (all(0:1 %in% minority)) +(minority == 1 & sapply(sentencing, function(sen) any(sen < sentencing[minority == 0]))) else 0L
) %>%
ungroup()
# # A tibble: 6 x 5
# ID minority sentencing stricter lenient
# <int> <int> <int> <int> <int>
# 1 1 1 10 1 0
# 2 1 0 5 0 0
# 3 1 0 5 0 0
# 4 2 0 20 0 0
# 5 2 1 15 0 1
# 6 2 0 20 0 0
注意:我用if (all(0:1 %in% minority))
作为sapply(.)
的序,因为我希望它对没有找到两个sentencing
1值的ID
s是鲁棒的,其中缺少一个可能会降低计算值(如果不是错误的话)。
旁注:您似乎使用0
s和1
s作为布尔指示符,而不是序数或连续指示符。正因为如此,出于声明性的原因,我发现使用真正的logical
s:更好
dat %>%
group_by(ID) %>%
mutate(
stricter = if (all(0:1 %in% minority)) (minority == 1 & sapply(sentencing, function(sen) any(sen > sentencing[minority == 0]))) else FALSE,
lenient = if (all(0:1 %in% minority)) (minority == 1 & sapply(sentencing, function(sen) any(sen < sentencing[minority == 0]))) else FALSE
) %>%
ungroup()
数据
dat <- structure(list(ID = c(1L, 1L, 1L, 2L, 2L, 2L), minority = c(1L, 0L, 0L, 0L, 1L, 0L), sentencing = c(10L, 5L, 5L, 20L, 15L, 20L)), class = "data.frame", row.names = c(NA, -6L))