Получить все строки до и n строк после указанного значения c в группе - PullRequest
0 голосов
/ 27 февраля 2020

Я ищу простой код R / SQL, который выполняет следующие действия. В пределах указанной фирмы c она ищет первый экземпляр 1 в столбце VALUE, затем

  1. извлекает все строки до этого (которые будут иметь 0 в столбце VALUE) и
  2. ровно две строки после этого, пока эти две строки имеют ЗНАЧЕНИЕ 0.

Код делает это для всех фирм.

, поэтому эта таблица ... .

----------------------
| FIRM | YEAR | VALUE |
----------------------
|  A   | 2007 |  0   |
----------------------
|  A   | 2008 |  0   |
----------------------
|  A   | 2009 |  0   |
----------------------
|  A   | 2010 |  1   |
----------------------
|  A   | 2011 |  0   |
----------------------
|  A   | 2012 |  0   |
----------------------
|  B   | 2009 |  0   |
----------------------
|  B   | 2010 |  1   |
----------------------
|  B   | 2011 |  0   |
----------------------
|  C   | 2010 |  0   |
----------------------
|  C   | 2011 |  1   |
----------------------
|  C   | 2012 |  1   |
----------------------

будет выглядеть так ...

--------------------------
| FIRM  | YEAR  | VALUE  |
--------------------------
|  A   | 2007 |  0   |
----------------------
|  A   | 2008 |  0   |
----------------------
|  A   | 2009 |  0   |
----------------------
|  A   | 2010 |  1   |
----------------------
|  A   | 2011 |  0   |
----------------------
|  A   | 2012 |  0   |
----------------------

Буду очень признателен за вашу помощь. Спасибо.

Ответы [ 2 ]

1 голос
/ 27 февраля 2020

Вы можете вычислить минимальный год и затем использовать эту информацию:

with t as (
      select firm, min(year) as min_year_1
      from tab t
      where value = 1
      group by firm
     )
select t.*
from (select t.*,
             lag(value) over (partition by firm order by year) as prev_value,
             lead(value) over (partition by firm order by year) as next_value
      from tab t
     ) t join
     tt
     on tt.firm = t.firm
where t.year <= tt.min_year or
      (t.year = tt.min_year + 1 and
       t.value = 0 and
       t.next_value = 0
      ) or
      (t.year = tt.min_year + 2 and
       t.value = 0 and
       t.prev_value = 0
      );

Последнее условие в обеих строках после 0 довольно сложно.

Предполагается, что год являются последовательными без пробелов, что согласуется с данными в вашем вопросе.

РЕДАКТИРОВАТЬ:

Вы можете сделать это только с помощью оконных функций:

select t.*
from (select t.*,
             count(*) over (partition by firm, running_value) as cnt,
             row_number() over (partition by firm, running_value) as seqnum
      from (select t.*,
                   sum(value) over (partition by firm order by year) as running_value
            from tab t
           ) t
      ) t
where running_value = 0 or
      (running_value = 1 and seqnum = 1) or  -- first "1"
      (running_value = 1 and seqnum <= 3 and
       cnt >= 3);
0 голосов
/ 27 февраля 2020

Используя R, вы можете создать функцию, которая будет возвращать выбранные номера строк.

get_rows <- function(VALUE) {
   ind <- which(VALUE == 1)[1]
   if ((ind + 2) <= length(VALUE) && all(VALUE[c(ind + 1,ind + 2)] == 0))
     sort(c(which(VALUE[seq_len(ind + 2)] == 0), ind))
   else 0
}

и применять ее для каждого FIRM.

library(dplyr)
df %>% group_by(FIRM) %>% slice(get_rows(VALUE))

#  FIRM   YEAR VALUE
#  <fct> <int> <int>
#1 A      2007     0
#2 A      2008     0
#3 A      2009     0
#4 A      2010     1
#5 A      2011     0
#6 A      2012     0

данные

df <- structure(list(FIRM = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 
2L, 2L, 3L, 3L, 3L), .Label = c("A", "B", "C"), class = "factor"), 
YEAR = c(2007L, 2008L, 2009L, 2010L, 2011L, 2012L, 2009L, 
2010L, 2011L, 2010L, 2011L, 2012L), VALUE = c(0L, 0L, 0L, 
1L, 0L, 0L, 0L, 1L, 0L, 0L, 1L, 1L)), class = "data.frame",row.names = c(NA, -12L))
...