R: Group by one column, and return the first row that has a value greater than 0 in any of the other columns and then return all rows after this row

时间:2018-09-18 20:34:30

标签: r

enter image description here

I'm new to R programming and hope someone could help me with the situation below:

I have a dataframe shown in the picture (Original Dataframe), I would like to return the first record grouped by the [ID] column that has a value >= 1 in any of the four columns (A, B, C, or D) and all the records after based off the [Date] column (the desired dataframe should look like the Output Dataframe shown in the picture). Basically, remove all the records highlighted in yellow. I would appreciate greatly if you can provide the R code to achieve this.

structure(list(ID = c(101L, 101L, 101L, 101L, 101L, 101L, 103L, 
103L, 103L, 103L), Date = c(43338L, 43306L, 43232L, 43268L, 43183L, 
43144L, 43310L, 43246L, 43264L, 43209L), A = c(0L, 0L, 0L, 0L, 
0L, 0L, 0L, 1L, 0L, 0L), B = c(0L, 2L, 0L, 0L, 0L, 0L, 0L, 1L, 
0L, 0L), C = c(0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), D = c(0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L)), .Names = c("ID", "Date", 
"A", "B", "C", "D"), row.names = c(NA, -10L), class = c("data.table", 
"data.frame"))

2 个答案:

答案 0 :(得分:0)

这是一个解决方案,

    ID       Date A B C D
1  101 26.08.2018 0 0 0 0
2  101 25.07.2018 0 2 0 0
3  101 12.05.2018 0 0 1 0
4  101 17.06.2018 0 0 0 0
5  101 24.03.2018 0 0 0 0
6  101 13.02.2018 0 0 0 0
7  103 29.07.2018 0 0 0 0
8  103 26.05.2018 1 1 0 0
9  103 13.06.2018 0 0 0 0
10 103 19.04.2018 0 0 0 0


data$Check <- rowSums(data[3:6]) 

data$Date <- as.Date(data$Date , "%d.%m.%Y")


data <- data[order(data$ID,data$Date),]


id <- unique(data$ID)

for(i in 1:length(id)) {

    data_sample <- data[data$ID == id[i],]

    data_sample <- data_sample[ min(which(data_sample$Check>0 )):nrow(data_sample),]

    if(i==1) {

        final <- data_sample


    } else {

        final <- rbind(final,data_sample)

    }

}

final <- final[,-7]

   ID       Date A B C D
3 101 2018-05-12 0 0 1 0
4 101 2018-06-17 0 0 0 0
2 101 2018-07-25 0 2 0 0
1 101 2018-08-26 0 0 0 0
8 103 2018-05-26 1 1 0 0
9 103 2018-06-13 0 0 0 0
7 103 2018-07-29 0 0 0 0

答案 1 :(得分:0)

这是一个tidyverse解决方案。 filter条件值得解释:

  1. 首先,我们按IDDate以及group_by ID
  2. 进行排序
  3. 然后,对于每个ID(由于我们按ID分组),我们应用了过滤条件:
    1. 针对每一行测试是否有任何变量为> 0
    2. 在这种情况下获取(组中)所有行的行号
    3. 找到最低的一个(由于行按日期排序,因此最早的一个)
    4. 获取该行的Date的值。
    5. 然后过滤其中Date>=的行。

由于我们仍按ID进行分组,因此所有这些计算将分别针对每个组进行:

df %>%
    arrange(ID, Date) %>%
    group_by(ID) %>%
    filter(Date >= Date[min(which(A > 0 | B > 0 | C > 0 | D > 0))])

# A tibble: 7 x 6
# Groups:   ID [2]
     ID  Date     A     B     C     D
  <int> <int> <int> <int> <int> <int>
1   101 43232     0     0     1     0
2   101 43268     0     0     0     0
3   101 43306     0     2     0     0
4   101 43338     0     0     0     0
5   103 43246     1     1     0     0
6   103 43264     0     0     0     0
7   103 43310     0     0     0     0