当前位置: 首页 > 知识库问答 >
问题:

选择与某一行具有相同值的上一行和下一行

郭翰翮
2023-03-14

我使用键idtime构建以下面板数据:

pdata <- tibble(
  id = rep(1:10, each = 5),
  time = rep(2016:2020, times = 10),
  value = c(c(1,1,1,0,0), c(1,1,0,0,0), c(0,0,1,0,0), c(0,0,0,0,0), c(1,0,0,0,1), c(0,1,1,1,0), c(0,1,1,1,1), c(1,1,1,1,1), c(1,0,1,1,1), c(1,1,0,1,1))
)
pdata
# A tibble: 50 × 3
      id  time value
   <int> <int> <dbl>
 1     1  2016     1
 2     1  2017     1
 3     1  2018     1
 4     1  2019     0
 5     1  2020     0
 6     2  2016     1
 7     2  2017     1
 8     2  2018     0
 9     2  2019     0
10     2  2020     0
# … with 40 more rows

让我们假设2018年发生了一次冲击。我希望通过id对上一行和下一行进行切片,这些行的值与shock行的值相同。

我举几个例子来说明。对于id==5,数据集如下所示:

pdata %>% filter(id == 5)
# A tibble: 5 × 3
     id  time value
  <int> <int> <dbl>
1     5  2016     1
2     5  2017     0
3     5  2018     0
4     5  2019     0
5     5  2020     1

2018年id==5值为0,我希望保留上一行和下一行,包括当前行,因为所有这些观察值都具有相同的值,等于0。

# A tibble: 3 × 3
     id  time value
  <int> <int> <dbl>
1     5  2017     0
2     5  2018     0
3     5  2019     0

对于id==8,我希望得到:

# A tibble: 5 × 3
     id  time value
  <int> <int> <dbl>
1     8  2016     1
2     8  2017     1
3     8  2018     1
4     8  2019     1
5     8  2020     1

对于id==1,我希望获得空数据集,因为2017年的观察结果和2019年的观察结果对不具有相同的值。

最终数据集应为:

# A tibble: 19 × 3
      id  time value
   <int> <int> <dbl>
 1     4  2016     0
 2     4  2017     0
 3     4  2018     0
 4     4  2019     0
 5     4  2020     0
 6     5  2017     0
 7     5  2018     0
 8     5  2019     0
 9     6  2017     1
10     6  2018     1
11     6  2019     1
12     7  2017     1
13     7  2018     1
14     7  2019     1
15     8  2016     1
16     8  2017     1
17     8  2018     1
18     8  2019     1
19     8  2020     1

共有3个答案

鲜于念
2023-03-14

据我所知,这里有一个dplyr建议:

library(dplyr)

MyF <- function(id2, shock, nb_row) {
  values <- pdata %>%
    filter(id == id2) %>%
    pull(value)
  
  if (length(unique(values)) == 1) {
    pdata %>%
      filter(id == id2)
  } else {
    pdata %>%
      filter(id == id2) %>%
      filter(time >= shock - nb_row & time <= shock + nb_row) %>%
      filter(length(unique(value)) == 1)
  }
  
  
}

map_df(pdata %>%
         select(id) %>% 
         distinct() %>% 
         pull(),
       MyF,
       shock = 2018, nb_row = 1)

## Or map_df(1:8,MyF,shock = 2018, nb_row = 1)

输出:

# A tibble: 19 x 3
      id  time value
   <int> <int> <dbl>
 1     4  2016     0
 2     4  2017     0
 3     4  2018     0
 4     4  2019     0
 5     4  2020     0
 6     5  2017     0
 7     5  2018     0
 8     5  2019     0
 9     6  2017     1
10     6  2018     1
11     6  2019     1
12     7  2017     1
13     7  2018     1
14     7  2019     1
15     8  2016     1
16     8  2017     1
17     8  2018     1
18     8  2019     1
19     8  2020     1
融修平
2023-03-14

在每个“id”(by=id)中,使用rleid基于相等值的运行创建分组变量“r”。在每个“id”和运行(by=(id,r))中,检查是否至少存在焦点年(例如2018年)的上一年和下一年(if(总和(时间百分比,年)==3))。如果是这样,请在焦点年前后选择相同数量的行(min(c(shock-.I[1],.I[.N]-shock))。请注意,此处选择的年数可能因“id”而异。

library(data.table)
setDT(pdata)
yr = 2018
yr_rng = (yr - 1):(yr + 1)

pdata[ , r := rleid(value), by = id]
pdata[pdata[ , if(sum(time %in% yr_rng) == 3) {
  shock = .I[time == 2018]
  rng = min(c(shock - .I[1], .I[.N] - shock))
  (shock - rng):(shock + rng)
}, by = .(id, r)]$V1] 

    id time value r
 1:  4 2016     0 1
 2:  4 2017     0 1
 3:  4 2018     0 1
 4:  4 2019     0 1
 5:  4 2020     0 1
 6:  5 2017     0 2
 7:  5 2018     0 2
 8:  5 2019     0 2
 9:  6 2017     1 2
10:  6 2018     1 2
11:  6 2019     1 2
12:  7 2017     1 2
13:  7 2018     1 2
14:  7 2019     1 2
15:  8 2016     1 1
16:  8 2017     1 1
17:  8 2018     1 1
18:  8 2019     1 1
19:  8 2020     1 1

在每个“id”和运行(by=(id,r))中,检查重点年份(例如2018年)的上一年和下一年是否都存在(if(总和(时间百分比,年)==3))。如果是,请选择整个组(.SD)。


pdata[ , r := rleid(value), by = id]
pdata[ , if(sum(time %in% yr_rng) == 3) .SD, by = .(id, r)]

    id r time value
 1:  4 1 2016     0
 2:  4 1 2017     0
 3:  4 1 2018     0
 4:  4 1 2019     0
 5:  4 1 2020     0
 6:  5 2 2017     0
 7:  5 2 2018     0
 8:  5 2 2019     0
 9:  6 2 2017     1
10:  6 2 2018     1
11:  6 2 2019     1
12:  7 2 2017     1
13:  7 2 2018     1
14:  7 2 2019     1
15:  7 2 2020     1
16:  8 1 2016     1
17:  8 1 2017     1
18:  8 1 2018     1
19:  8 1 2019     1
20:  8 1 2020     1
上官彬
2023-03-14

data.table解决方案:

# load the package & convert data to a data.table
library(data.table)
setDT(pdata)

# define shock-year and number of previous/next rows
shock <- 2018
n <- 2

# filter
pdata[, .SD[value == value[time == shock] &
              between(time, shock - n, shock + n) & 
              value == rev(value)][.N > 1 & all(diff(time) == 1)]
      , by = id]

其中:

    id time value
 1:  4 2016     0
 2:  4 2017     0
 3:  4 2018     0
 4:  4 2019     0
 5:  4 2020     0
 6:  5 2017     0
 7:  5 2018     0
 8:  5 2019     0
 9:  6 2017     1
10:  6 2018     1
11:  6 2019     1
12:  7 2017     1
13:  7 2018     1
14:  7 2019     1
15:  8 2016     1
16:  8 2017     1
17:  8 2018     1
18:  8 2019     1
19:  8 2020     1

使用数据:

pdata <- data.frame(
  id = rep(1:10, each = 5),
  time = rep(2016:2020, times = 10),
  value = c(c(1,1,1,0,0), c(1,1,0,0,0), c(0,0,1,0,0), c(0,0,0,0,0), c(1,0,0,0,1), c(0,1,1,1,0), c(0,1,1,1,1), c(1,1,1,1,1), c(1,0,1,1,1), c(1,1,0,1,1))
)
 类似资料:
  • 问题内容: 假设我有这个(MySQL)数据库,按增加的时间戳排序: 如何从该系统的上一行中选择StatusA更改的行?StatusB无关紧要(我在此问题中展示它只是为了说明每个系统可能有许多连续的行,其中StatusA不变)。在上面的示例中,查询应返回2011-01-03行(对于SystemA,StatusA在2011-01-01和2011-01-03之间更改),2011-01-06、2011-0

  • 问题内容: 我有一张桌子,像这样: 我想选择具有相同基因座和染色体的所有行。例如,第3行和第4行。一次可能有2个以上,并且它们可能不是按顺序排列的。 我尝试了这个: 但是,即使重复,它总是返回第3行,从不返回第4行。我想我缺少明显而简单的东西,但我茫然。 有人可以帮忙吗? 问题答案: 您需要了解,当您在查询中包含内容时,您是在告诉SQL合并行。您将为每个唯一值获得一行。在随后过滤这些组。通常,您可

  • 我有一个学生表和一个成绩表。 < li >学生具有学生id(主键)、姓名、出生日期、地址、电子邮件和级别列。 < li>Grades包含列student_id(主/外键)、course_id(主/外键)和grade。 “成绩”如下所示: 这不是整个表格,但你明白了要点。我正在尝试编写一个查询,选择学生的姓名和该学生的最高分。由于我是SQL的新手,所以这对我来说有点令人困惑。到目前为止,我的尝试是这

  • 本文向大家介绍根据DataFrame某一列的值来选择具体的某一行方法,包括了根据DataFrame某一列的值来选择具体的某一行方法的使用技巧和注意事项,需要的朋友参考一下 原始数据的DF: 此时,我要选择列名isInfected为“手足口病”的样本行: 总结:选择DataFrame里面某一列等于某个值的所有行,用一条命令即可解决即: 以上这篇根据DataFrame某一列的值来选择具体的某一行方法就

  • 问题内容: 该主题的解决方案使我不知所措。 我有一个看起来像的表格(除与我的问题无关的其他字段之外): 名称,卡号,会员类型 现在,我想要一个显示卡号和成员类型相同的行的视图。这两个字段都是整数。名称为VARCHAR。名称不是唯一的,并且相同的名称也应显示重复的卡号,会员类型。 即,如果下表是表格: 我想要: 只需按卡号排序即可使其对人类有用。 最有效的方法是什么? 问题答案: 由于您提到的名称可

  • exTab 如何使用SQL(与mySQL一起)只返回col1中具有多个相同值、col2中具有多个相同值、但COL3中具有唯一值的行? 例如,在上面的表(exTab)中,val1在col1中出现了4次,对于这4次,val4在col2中出现了3次,但是对于这3次,val7在col3中只出现了一次,所以我想返回这一行(第1行)。考虑到这些条件,第1行将是我希望从此表返回的唯一一行。 我试过和group