Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
选择R中每个ID每个日期的第一个正匹配项_R - Fatal编程技术网

选择R中每个ID每个日期的第一个正匹配项

选择R中每个ID每个日期的第一个正匹配项,r,R,我有一个数据框架,随着时间的推移,观察结果会有所不同。只要一个ID的“匹配”值为正值,就必须删除后面日期中具有该ID的行。这是一个示例数据帧: Date ID Match 2018-06-06 5 1 2018-06-06 6 0 2018-06-07 5 1 2018-06-07 6 0 2018-06-07 7 1 2018-06-08 5 0 2018-06-08 6 1 2018-06-08 7 1 2018

我有一个数据框架,随着时间的推移,观察结果会有所不同。只要一个ID的“匹配”值为正值,就必须删除后面日期中具有该ID的行。这是一个示例数据帧:

      Date  ID  Match
2018-06-06  5    1
2018-06-06  6    0
2018-06-07  5    1
2018-06-07  6    0
2018-06-07  7    1
2018-06-08  5    0
2018-06-08  6    1
2018-06-08  7    1
2018-06-08  8    1
期望输出:

      Date  ID  Match
2018-06-06  5    1
2018-06-06  6    0
2018-06-07  6    0
2018-06-07  7    1
2018-06-08  6    1
2018-06-08  8    1
换言之,由于ID=5在2018-06-06具有正匹配,因此ID=5的行将在接下来的几天中删除,但保留该ID第一个正匹配的行

可复制示例:

Date <- c("2018-06-06","2018-06-06","2018-06-07","2018-06-07","2018-06-07","2018-06-08","2018-06-08","2018-06-08","2018-06-08")
ID <- c(5,6,5,6,7,5,6,7,8)
Match <- c(1,0,1,0,1,0,1,1,1)
df <- data.frame(Date,ID,Match)
日期单向:

library(data.table)
setDT(df)
df[, Match := as.integer(as.character(Match))] # fix bad format

df[, .SD[shift(cumsum(Match), fill=0) == 0], by=ID]

   ID       Date Match
1:  5 2018-06-06     1
2:  6 2018-06-06     0
3:  6 2018-06-07     0
4:  6 2018-06-08     1
5:  7 2018-06-07     1
6:  8 2018-06-08     1
我们希望在第一个匹配==1之后删除行


cumsum
获取匹配的累积和。在第一个匹配==1之前,它一直为零。我们希望保留后一行,因此在前一行中使用受@Frank answer启发的
shift

检查
cumsum

 library(dplyr)
 df %>% group_by(ID) %>% mutate(Flag = cumsum(as.numeric(Match))) %>%
        filter(Match==0 & Flag==0 | Match==1 & Flag==1)

 # A tibble: 6 x 4
 # Groups:   ID [4]
  Date       ID    Match  Flag
  <chr>      <chr> <chr> <dbl>
1 2018-06-06 5     1         1
2 2018-06-06 6     0         0
3 2018-06-07 6     0         0
4 2018-06-07 7     1         1
5 2018-06-08 6     1         1
6 2018-06-08 8     1         1
库(dplyr)
df%%>%group_by(ID)%%>%mutate(Flag=cumsum(as.numeric(Match)))%%
过滤器(匹配==0&Flag==0 |匹配==1&Flag==1)
#一个tibble:6x4
#组别:ID[4]
日期ID匹配标志
1 2018-06-06 5     1         1
2 2018-06-06 6     0         0
3 2018-06-07 6     0         0
4 2018-06-07 7     1         1
5 2018-06-08 6     1         1
6 2018-06-08 8     1         1
资料
Date这里有一种替代方法,我们发现每个
ID
Match
=1(即第一行为正匹配)的最小行数,并根据此进行过滤:

Date <- c("2018-06-06","2018-06-06","2018-06-07","2018-06-07","2018-06-07","2018-06-08","2018-06-08","2018-06-08","2018-06-08")
ID <- c(5,6,5,6,7,5,6,7,8)
Match <- c(1,0,1,0,1,0,1,1,1)
df <- as.data.frame(cbind(Date,ID,Match))

library(dplyr)

df %>%
  group_by(ID) %>%                                     # for each ID
  mutate(min_row = min(row_number()[Match == 1])) %>%  # get the first row where you have 1
  filter(row_number() <= min_row) %>%                  # keep previous rows and that row
  ungroup() %>%                                        # forget the grouping
  select(-min_row)                                     # remove unnecessary column

# # A tibble: 6 x 3
#   Date       ID    Match
#   <fct>      <fct> <fct>
# 1 2018-06-06 5     1    
# 2 2018-06-06 6     0    
# 3 2018-06-07 6     0    
# 4 2018-06-07 7     1    
# 5 2018-06-08 6     1    
# 6 2018-06-08 8     1  

下面是另一个
dplyr
选项:

library(dplyr)  
df %>%
  mutate(Date = as.Date(Date)) %>% 
  group_by(ID) %>%
  mutate(first_match = min(Date[Match == 1])) %>% 
  filter((Match == 1 & Date == first_match) | (Match == 0 & Date < first_match)) %>% 
  ungroup() %>% 
  select(-first_match)

# A tibble: 6 x 3
  Date       ID    Match
  <date>     <fct> <fct>
1 2018-06-06 5     1    
2 2018-06-06 6     0    
3 2018-06-07 6     0    
4 2018-06-07 7     1    
5 2018-06-08 6     1    
6 2018-06-08 8     1   
库(dplyr)
df%>%
变异(日期=as.Date(日期))%>%
分组依据(ID)%>%
变异(第一次匹配=min(日期[匹配=1]))%>%
筛选器((匹配==1和日期==第一次匹配)|(匹配==0和日期<第一次匹配))%>%
解组()%>%
选择(-first_match)
#一个tibble:6x3
日期ID匹配
1 2018-06-06 5     1    
2 2018-06-06 6     0    
3 2018-06-07 6     0    
4 2018-06-07 7     1    
5 2018-06-08 6     1    
6 2018-06-08 8     1   

我有另一种方法可以使用
dplyr

library(dplyr)
df %>% 
  group_by(ID) %>% 
  # You can use order(Date) if you don't want to coerce Date into date object
  mutate(ord = order(Date), first_match = min(ord[Match > 0]), ind = seq_along(Date)) %>% 
  filter(ind <= first_match) %>%
  select(Date:Match)
# A tibble: 6 x 3
# Groups:   ID [4]
  Date          ID Match
  <chr>      <dbl> <dbl>
1 2018-06-06     5     1
2 2018-06-06     6     0
3 2018-06-07     6     0
4 2018-06-07     7     1
5 2018-06-08     6     1
6 2018-06-08     8     1
库(dplyr)
df%>%
分组依据(ID)%>%
#如果不想将日期强制转换为日期对象,可以使用order(Date)
变异(ord=订单(日期),首次匹配=最小(ord[匹配>0]),ind=顺序(日期))%>%
过滤器(ind%
选择(日期:匹配)
#一个tibble:6x3
#组别:ID[4]
日期ID匹配
1 2018-06-06     5     1
2 2018-06-06     6     0
3 2018-06-07     6     0
4 2018-06-07     7     1
5 2018-06-08     6     1
6 2018-06-08     8     1

如果特定ID的第一个1后面跟着该特定ID的0,则此操作将中断。@AntoniosK您是正确的,请您现在检查它。是的,现在它可以工作了(即解决我提到的问题)。仅供参考,您不需要
cbind
。只需执行
data.frame(日期、ID、匹配)
。使用
cbind
,将生成一个矩阵,因此所有三列都将成为因子或字符串。
library(dplyr)  
df %>%
  mutate(Date = as.Date(Date)) %>% 
  group_by(ID) %>%
  mutate(first_match = min(Date[Match == 1])) %>% 
  filter((Match == 1 & Date == first_match) | (Match == 0 & Date < first_match)) %>% 
  ungroup() %>% 
  select(-first_match)

# A tibble: 6 x 3
  Date       ID    Match
  <date>     <fct> <fct>
1 2018-06-06 5     1    
2 2018-06-06 6     0    
3 2018-06-07 6     0    
4 2018-06-07 7     1    
5 2018-06-08 6     1    
6 2018-06-08 8     1   
library(dplyr)
df %>% 
  group_by(ID) %>% 
  # You can use order(Date) if you don't want to coerce Date into date object
  mutate(ord = order(Date), first_match = min(ord[Match > 0]), ind = seq_along(Date)) %>% 
  filter(ind <= first_match) %>%
  select(Date:Match)
# A tibble: 6 x 3
# Groups:   ID [4]
  Date          ID Match
  <chr>      <dbl> <dbl>
1 2018-06-06     5     1
2 2018-06-06     6     0
3 2018-06-07     6     0
4 2018-06-07     7     1
5 2018-06-08     6     1
6 2018-06-08     8     1