谁能想到如何在R中做到这一点?
简单数据:
seq<-c("A","A","A","B","B","B","B")
rank<-c(1,2,3,1,2,3,4)
match<-c("y","n","y","n","n","y","y")
df<- as.data.frame(cbind(seq,rank,match))
seq rank match
1 A 1 y
2 A 2 n
3 A 3 y
4 B 1 n
5 B 2 n
6 B 3 y
7 B 4 y
我想创建一个‘choose’
列,其中,对于每个唯一的序列,y
下的match
的第一个实例都被赋予T
,其余所有给定F
。
所需的输出为:
seq rank match choose
1 A 1 y T
2 A 2 n F
3 A 3 y F
4 B 1 n F
5 B 2 n F
6 B 3 y T
7 B 4 y F
通过将ifelse
语句与滞后值结合起来,可以很容易地为等级1和等级2返回正确的值,但是一旦等级>2
,我就很困惑。
真实的dataset
包含+100k rows
,排名可能上升到数百,因此我不想仅仅扩展ifelse
语句来使用滞后检查上面的值。
我的最终目标是从“选择”下的所有T中创建一个新的dataset
,因此,如果有人知道如何直接将它们拉出而不创建新的列,那就更好了!
我猜测ifelse
语句是一种愚蠢的做法,但是我被困在:/
任何帮助将不胜感激:)
答案 0 :(得分:1)
一种dplyr
可能是:
df %>%
group_by(seq) %>%
mutate(choose = +(match == "y") * (cumsum(match == "y") == 1))
seq rank match choose
<fct> <fct> <fct> <int>
1 A 1 y 1
2 A 2 n 0
3 A 3 y 0
4 B 1 n 0
5 B 2 n 0
6 B 3 y 1
7 B 4 y 0
如果您想使用TRUE / FALSE值,则:
df %>%
group_by(seq) %>%
mutate(choose = as.logical(+(match == "y") * (cumsum(match == "y") == 1)))
seq rank match choose
<fct> <fct> <fct> <lgl>
1 A 1 y TRUE
2 A 2 n FALSE
3 A 3 y FALSE
4 B 1 n FALSE
5 B 2 n FALSE
6 B 3 y TRUE
7 B 4 y FALSE
与base R
相同:
with(df, ave(match, seq, FUN = function(x) +(x == "y") * (cumsum(x == "y") == 1)))
或者:
with(df, ave(match, seq, FUN = function(x) as.logical(+(x == "y") * (cumsum(x == "y") == 1))))
答案 1 :(得分:1)
您可以尝试类似:
sql_mode=''
答案 2 :(得分:1)
一个选项:
df %>%
group_by(seq) %>%
mutate(choose = row_number() %in% which(match == 'y')[1])
输出:
# A tibble: 7 x 4
# Groups: seq [2]
seq rank match choose
<fct> <fct> <fct> <lgl>
1 A 1 y TRUE
2 A 2 n FALSE
3 A 3 y FALSE
4 B 1 n FALSE
5 B 2 n FALSE
6 B 3 y TRUE
7 B 4 y FALSE
答案 3 :(得分:1)
您可以将新列创建为逻辑向量,当TRUE
时,该列为match == 'y'
,并且该行是(match,seq)对(即rowid(match, seq) == 1
)的第一个出现< / p>
library(data.table)
setDT(df)
df[, choose := match == 'y' & rowid(match, seq) == 1]
df
# seq rank match choose
# 1: A 1 y TRUE
# 2: A 2 n FALSE
# 3: A 3 y FALSE
# 4: B 1 n FALSE
# 5: B 2 n FALSE
# 6: B 3 y TRUE
# 7: B 4 y FALSE
或者直接创建数据子集而无需创建新列
df[match == 'y' & rowid(match, seq) == 1]
# seq rank match
# 1: A 1 y
# 2: B 3 y
答案 4 :(得分:1)
一个选项是
library(dplyr)
df %>%
group_by(seq) %>%
mutate(choose = row_number() == match("y", match))
# A tibble: 7 x 4
# Groups: seq [2]
# seq rank match choose
# <fct> <fct> <fct> <lgl>
#1 A 1 y TRUE
#2 A 2 n FALSE
#3 A 3 y FALSE
#4 B 1 n FALSE
#5 B 2 n FALSE
#6 B 3 y TRUE
#7 B 4 y FALSE