简体   繁体   中英

Count how many times a value has appeared in a vector [with conditions in R]

I have the following dataset and would like to count how many times in a vector a certain condition has occured:

structure(list(ID = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 
3L, 3L), Stimuli = c(1L, 0L, 0L, 1L, 1L, 1L, 0L, 1L, 0L, 1L, 
0L, 1L)), .Names = c("ID", "Stimuli"), class = c("tbl_df", "tbl", 
"data.frame"), row.names = c(NA, -12L), spec = structure(list(
    cols = structure(list(ID = structure(list(), class = 
c("collector_integer", 
    "collector")), Stimuli = structure(list(),
class = c("collector_integer", 
    "collector"))), .Names = c("ID", "Stimuli")), default = structure(list(),
class = c("collector_guess", 
    "collector"))), .Names = c("cols", "default"), class = "col_spec"))

Only counting for every ID seperatly and only if the value of Stimuli has been 1. The result would then be summarized in an extra row and look like this:

ID  Stimuli Count
1      1    1
1      0    0
1      0    0
1      1    2
2      1    1
2      1    2
2      0    0
2      1    3
3      0    0
3      1    1
3      0    0
3      1    2

I am aware of as.data.frame(table(df)) for getting the frequency, but in this case i would like to keep every row and also only count in every ID-Sequence.

We can use a group_by cumulative sum ( cumsum ) based on an ifelse condition on 'Stimuli' that are 1

library(dplyr)
d1 %>% 
   group_by(ID) %>% 
   mutate(Count = ifelse(Stimuli == 1, cumsum(Stimuli), 0))
# A tibble: 12 x 3
# Groups:   ID [3]
#      ID Stimuli Count
#   <int>   <int> <dbl>
# 1     1       1     1
# 2     1       0     0
# 3     1       0     0
# 4     1       1     2
# 5     2       1     1
# 6     2       1     2
# 7     2       0     0
# 8     2       1     3
# 9     3       0     0
#10     3       1     1
#11     3       0     0
#12     3       1     2

Or another option is data.table

library(data.table)
setDT(df1)[Stimuli == 1, Count := seq_len(.N), by = ID][is.na(Count), Count := 0][]

Or using ave from base R

with(d1, Stimuli *ave(Stimuli, ID, FUN = cumsum))

You can use data.table package:

 library(data.table)
 setDT(df)[, Count := cumsum(Stimuli)*Stimuli, by=ID]


#     ID Stimuli Count 
#  1:  1       1     1 
#  2:  1       0     0 
#  3:  1       0     0 
#  4:  1       1     2 
#  5:  2       1     1 
#  6:  2       1     2 
#  7:  2       0     0 
#  8:  2       1     3 
#  9:  3       0     0 
# 10:  3       1     1 
# 11:  3       0     0 
# 12:  3       1     2

With base R only, a bit more complicated. I'll name the df dat .

dat1 <- dat
dat1$Count <- 0
sp <- split(dat1, dat1$ID)
res <- do.call(rbind, lapply(sp, function(x){
    inx <- x$Stimuli != 0
    x$Count[inx] <- cumsum(x$Stimuli[inx])
    x
}))
res

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM