[英]R: By group, test if for each value of one variable, that value exists in another variable
我有一個數據框結構類似於:
a <- c(1,1,1,2,2,2,3,3,3,3,4,4)
b <- c(1,2,3,1,2,3,1,2,3,4,1,2)
c <- c(NA, NA, 2, NA, 1, 1, NA, NA, 1, 1, NA, NA)
df <- data.frame(a,b,c)
其中a
和b
唯一地標識觀察。 我想創建一個新變量d
,它指示b
每個觀察值是否在c
中至少存在一次,由a
分組。 這樣d
將是:
[1] 0 1 0 1 0 0 1 0 0 0 0 0
我可以編寫一個for循環來完成這個技巧,
attach(df)
for (i in unique(a)) {
for (j in b[a == i]) {
df$d[a == i & b == j] <- ifelse(j %in% c[a == i], 1, 0)
}
}
但是肯定在R中必須有更清潔/更快的方法來實現相同的結果嗎?
使用data.table
:
library(data.table)
setDT(df) #convert df to a data.table without copying
# +() is code golf for as.integer
df[ , d := +(b %in% c), by = a]
# a b c d
# 1: 1 1 NA 0
# 2: 1 2 NA 1
# 3: 1 3 2 0
# 4: 2 1 NA 1
# 5: 2 2 1 0
# 6: 2 3 1 0
# 7: 3 1 NA 1
# 8: 3 2 NA 0
# 9: 3 3 1 0
# 10: 3 4 1 0
# 11: 4 1 NA 0
# 12: 4 2 NA 0
為那些說服添加dplyr
版本。 歸功於@akrun的所有功勞。
library(dplyr)
df %>% group_by(a) %>% mutate(d = +(b %in% c))
對后代來說,還有一個base
R
版本(通過下面的@thelatemail)
df <- df[order(df$a, df$b), ]
df$d <- unlist(by(df, df$a, FUN = function(x) (x$b %in% x$c) + 0L ))
MichaelChirico的上述答案顯然運作良好且是正確的。 我很少使用data.table所以我不懂語法。 這是一種在沒有data.table的情況下獲得相同結果的方法。
invisible(lapply(unique(df$a), function(x) {
df$d[df$a==x] <<- 0L + (df$b[df$a==x] %in% df$c[df$a==x])
}))
此代碼獲取a的所有唯一級別,然后使用您請求的邏輯修改該級別的data.frame。 << - 是必要的,因為否則將僅在apply的范圍內修改df而不是.GlobalEnv。 使用<< - 它找到定義了df的父環境並在那里設置df。
另外,請注意+“技巧”的略有不同的版本,其中前導0使讀者更清楚結果向量是一個整數,因為它必須以這種方式進行轉換才能使加法工作。 0之后的L表示0是整數而不是雙精度。 請注意,MichaelChirico用於此轉換的表示法給出了相同的結果(類整數列)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.