【问题标题】:How to create new variables based on a binary variable in a grouped data set in R?如何基于 R 中分组数据集中的二进制变量创建新变量?
【发布时间】:2020-11-18 10:00:50
【问题描述】:

数据集有 3 列——第 1 列是“id”,第 2 列是“year”,第 3 列是“node”。第三列是二进制变量。现在,我们需要修复第 3 列“节点”上的数据错误,规则如下。

1)在每个id内,node=1的最后一个值之前的所有值都应该等于1。在node=1之前不应该出现node=0。它应该只停留在 node=1 的所有年份,或者在某个时间点从 node=1 变为 node=0。

2)在每个id内,如果节点从year1到year8的所有值都等于(0或1),那么我们必须保持它们不变。

综上所述,修正后的数据集应该是这样的,

 id     node   year
383100111   1   1
383100111   1   2
383100111   1   3
383100111   1   4
383100111   1   5
383100111   1   6
383100111   1   7
383100111   0   8
383100222   1   1
383100222   1   2
383100222   1   3
383100222   1   4
383100222   1   5
383100222   1   6
383100222   1   7
383100222   1   8
383100333   1   1
383100333   1   2
383100333   1   3
383100333   1   4
383100333   1   5
383100333   1   6
383100333   1   7
383100333   1   8
383100444   1   1
383100444   1   2
383100444   1   3
383100444   1   4
383100444   1   5
383100444   1   6
383100444   1   7
383100444   0   8
383100555   1   1
383100555   1   2
383100555   1   3
383100555   1   4
383100555   1   5
383100555   1   6
383100555   1   7
383100555   1   8
383100666   0   1
383100666   0   2
383100666   0   3
383100666   0   4
383100666   0   5
383100666   0   6
383100666   0   7
383100666   0   8
383100777   1   1
383100777   1   2
383100777   1   3
383100777   1   4
383100777   1   5
383100777   1   6
383100777   1   7
383100777   1   8

有错误的原始数据集结构如下,

structure(list(id = c(383100111, 383100111, 383100111, 383100111, 
383100111, 383100111, 383100111, 383100111, 383100222, 383100222, 
383100222, 383100222, 383100222, 383100222, 383100222, 383100222, 
383100333, 383100333, 383100333, 383100333, 383100333, 383100333, 
383100333, 383100333, 383100444, 383100444, 383100444, 383100444, 
383100444, 383100444, 383100444, 383100444, 383100555, 383100555, 
383100555, 383100555, 383100555, 383100555, 383100555, 383100555, 
383100666, 383100666, 383100666, 383100666, 383100666, 383100666, 
383100666, 383100666, 383100777, 383100777, 383100777, 383100777, 
383100777, 383100777, 383100777, 383100777), node = c(1, 1, 1, 
0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 
0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1), year = c(1, 2, 3, 4, 5, 6, 
7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 
4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 
1, 2, 3, 4, 5, 6, 7, 8)), row.names = c(NA, 56L), class ="data.frame")->dataframe

谢谢!

【问题讨论】:

  • 我可以看到您指定的条件与显示的输出之间存在一些矛盾。你能再检查一次吗?如果我错过了什么,请告诉我。
  • 很抱歉给您带来了困惑。我已经对错字进行了更改。
  • 还请说明在序列 1,0,1 的情况下是否应更改为 1,1,1 或 1,0,0?
  • 应该改为1,1,1。

标签: r rolling-computation


【解决方案1】:

试试这个代码

library(tidyverse)
df_repaired <- df %>% group_by(id) %>%
  mutate(col1 = cumsum(node)) %>%
  mutate(node2 = ifelse(last(col1)==col1 & node == 0, 0, 1)) %>%
  ungroup() %>%
  select(-col1, -node) %>%
  rename(node = node2)

> df_repaired
# A tibble: 56 x 3
          id  year  node
       <dbl> <dbl> <dbl>
 1 383100111     1     1
 2 383100111     2     1
 3 383100111     3     1
 4 383100111     4     1
 5 383100111     5     1
 6 383100111     6     1
 7 383100111     7     1
 8 383100111     8     0
 9 383100222     1     1
10 383100222     2     1
# ... with 46 more rows

方法解释:

  1. 字段 node 的累积求和。为此cumsum() 已被使用
  2. 检查累积总和何时停止进一步增加。这通过ifelse 条件语句在每个组中使用last 值进行了检查。为了排除节点中的最后一个 1,这也包含在 &amp; 运算符的条件中。

为了进一步解释这些事情,让我们在不删除创建的虚拟列的情况下使用代码..

df_repaired <- df %>% group_by(id) %>%
  mutate(col1 = cumsum(node)) %>%
  mutate(node2 = ifelse(last(col1)==col1 & node == 0, 0, 1)) %>%
  ungroup()

> print(df_repaired, n=56)
# A tibble: 56 x 5
          id  node  year  col1 node2
       <dbl> <dbl> <dbl> <dbl> <dbl>
 1 383100111     1     1     1     1
 2 383100111     1     2     2     1
 3 383100111     1     3     3     1
 4 383100111     0     4     3     1
 5 383100111     1     5     4     1
 6 383100111     0     6     4     1
 7 383100111     1     7     5     1
 8 383100111     0     8     5     0
 9 383100222     0     1     0     1
10 383100222     1     2     1     1
11 383100222     0     3     1     1
12 383100222     1     4     2     1
13 383100222     0     5     2     1
14 383100222     0     6     2     1
15 383100222     1     7     3     1
16 383100222     1     8     4     1
17 383100333     1     1     1     1
18 383100333     0     2     1     1
19 383100333     0     3     1     1
20 383100333     0     4     1     1
21 383100333     1     5     2     1
22 383100333     1     6     3     1
23 383100333     0     7     3     1
24 383100333     1     8     4     1
25 383100444     0     1     0     1
26 383100444     0     2     0     1
27 383100444     1     3     1     1
28 383100444     1     4     2     1
29 383100444     0     5     2     1
30 383100444     1     6     3     1
31 383100444     1     7     4     1
32 383100444     0     8     4     0
33 383100555     1     1     1     1
34 383100555     0     2     1     1
35 383100555     1     3     2     1
36 383100555     1     4     3     1
37 383100555     1     5     4     1
38 383100555     1     6     5     1
39 383100555     0     7     5     1
40 383100555     1     8     6     1
41 383100666     0     1     0     0
42 383100666     0     2     0     0
43 383100666     0     3     0     0
44 383100666     0     4     0     0
45 383100666     0     5     0     0
46 383100666     0     6     0     0
47 383100666     0     7     0     0
48 383100666     0     8     0     0
49 383100777     1     1     1     1
50 383100777     1     2     2     1
51 383100777     1     3     3     1
52 383100777     1     4     4     1
53 383100777     1     5     5     1
54 383100777     1     6     6     1
55 383100777     1     7     7     1
56 383100777     1     8     8     1

【讨论】:

  • 只剩下 10 个观察值了吗?
  • 我已将您的回答评为有用!你能在这里解释一下 cumsum 函数的目的吗?我真的不完全明白。谢谢。
  • 是的。我只是想学习,所以希望你能澄清你的代码的含义。谢谢。
  • 我已经用解释编辑了我的答案!请看那个。我使用了简单的逻辑,0 添加到某个值时返回相同的值。使用该列中的最后一个值检查每一列的该值,以确保它是该组中的最后一个0。对于最后一个 0 起,它已更改为 0,其他所有内容均更改为 1。这是否澄清了您的疑虑?
  • 我还是不知道你为什么要使用cumsum函数。
【解决方案2】:

另一种策略,可能更容易理解

library(tidyverse)

df_repaired <- df %>% group_by(id) %>%
  mutate(dummy_id = row_number(),
         col1 = last(which(node ==1)),
         node2 = ifelse(dummy_id > col1 | is.na(col1), 0, 1)) %>%
  ungroup() %>%
  select(-node, -dummy_id, -col1) %>%
  rename(node = node2)

> print(df_repaired, n=56)
# A tibble: 56 x 3
          id  year  node
       <dbl> <dbl> <dbl>
 1 383100111     1     1
 2 383100111     2     1
 3 383100111     3     1
 4 383100111     4     1
 5 383100111     5     1
 6 383100111     6     1
 7 383100111     7     1
 8 383100111     8     0
 9 383100222     1     1
10 383100222     2     1
11 383100222     3     1
12 383100222     4     1
13 383100222     5     1
14 383100222     6     1
15 383100222     7     1
16 383100222     8     1
17 383100333     1     1
18 383100333     2     1
19 383100333     3     1
20 383100333     4     1
21 383100333     5     1
22 383100333     6     1
23 383100333     7     1
24 383100333     8     1
25 383100444     1     1
26 383100444     2     1
27 383100444     3     1
28 383100444     4     1
29 383100444     5     1
30 383100444     6     1
31 383100444     7     1
32 383100444     8     0
33 383100555     1     1
34 383100555     2     1
35 383100555     3     1
36 383100555     4     1
37 383100555     5     1
38 383100555     6     1
39 383100555     7     1
40 383100555     8     1
41 383100666     1     0
42 383100666     2     0
43 383100666     3     0
44 383100666     4     0
45 383100666     5     0
46 383100666     6     0
47 383100666     7     0
48 383100666     8     0
49 383100777     1     1
50 383100777     2     1
51 383100777     3     1
52 383100777     4     1
53 383100777     5     1
54 383100777     6     1
55 383100777     7     1
56 383100777     8     1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-06
    • 1970-01-01
    • 2022-12-31
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多