Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

r - How to find first element of a group that fulfill a condition

structure(list(group = c(17L, 17L, 17L, 18L, 18L, 18L, 18L, 19L, 
19L, 19L, 20L, 20L, 20L, 21L, 21L, 22L, 23L, 24L, 25L, 25L, 25L, 
26L, 27L, 27L, 27L, 28L), var = c(74L, 49L, 1L, 74L, 1L, 49L, 
61L, 49L, 1L, 5L, 5L, 1L, 44L, 44L, 12L, 13L, 5L, 5L, 1L, 1L, 
4L, 4L, 1L, 1L, 1L, 49L), first = c(0, 0, 1, 0, 1, 0, 0, 0, 1, 
0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)), .Names = c("group", 
"var", "first"), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-26L))

With the data from the first two column I would like to create a third column (called first) where first == 1 only when var == 1 for the first time in a group. In other words I would like to mark first elements within group that fullfil var == 1. How can I do that in dplyr? Certainly group_by should be used but what next?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
library(dplyr)

df$first = NULL

df %>%
  group_by(group) %>%
  mutate(first = as.numeric(row_number() == min(row_number()[var == 1]))) %>%
  ungroup()

# # A tibble: 26 x 3
#   group   var first
#   <int> <int> <dbl>
# 1    17    74     0
# 2    17    49     0
# 3    17     1     1
# 4    18    74     0
# 5    18     1     1
# 6    18    49     0
# 7    18    61     0
# 8    19    49     0
# 9    19     1     1
# 10   19     5     0
# # ... with 16 more rows

The idea is to flag the minimum row number where var = 1, within each group.

This will return some warnings, because in some groups there are no var = 1 cases.

Another option would be this:

library(dplyr)

df$first = NULL

# create row id
df$id = seq_along(df$group)

df %>%
  filter(var == 1) %>%                         # keep cases where var = 1
  distinct(group, .keep_all = T) %>%           # keep distinct cases based on group
  mutate(first = 1) %>%                        # create first column
  right_join(df, by=c("id","group","var")) %>% # join back original dataset
  mutate(first = coalesce(first, 0)) %>%       # replace NAs with 0
  select(-id)                                  # remove row id

# # A tibble: 26 x 3
#   group   var first
#   <int> <int> <dbl>
# 1    17    74     0
# 2    17    49     0
# 3    17     1     1
# 4    18    74     0
# 5    18     1     1
# 6    18    49     0
# 7    18    61     0
# 8    19    49     0
# 9    19     1     1
#10    19     5     0
# # ... with 16 more rows

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...