首页 > 解决方案 > 当字符串出现在 R 中的单独列中时有条件地更改单元格值:时间序列

问题描述

问题:

“b”和“c”的起始状态由另一个表中的存在确定。

dd$b[1] <- ifelse( "b" %in% table,1,0)  
dd$c[1] <- ifelse( "c" %in% table,1,0)  

我希望提出一个公式:

  1. 检查中的值是否column a包含“lamp”和“b”,b如果是,则为 0,
  2. Else 检查 in 中的值是否column a包含“lion”和“b”,b如果是,则为 1,
  3. 或默认为上一行中的值b

为了包含示例输出,包含列 c 并且应遵循与上述相同的规则。

作为第三步,参考上面的单元格值是至关重要的,因为这被设计为随着时间的推移“改变状态”。

可粘贴表:

dd = read.table(header = T, text = "    time   a    b   c   d   s   
k   w
1   18:41  'b d cat'       1     0   1   0    0   1
2   18:43  'b d dog'       1     0   1   0    0   1
3   18:47  'b d lamp'      0     0   0   0    0   1
4   18:51  'b s dog'       0     0   0   0    0   1
5   18:52  'b k cat'       0     0   0   0    0   1
6   18:57  'b c lion'      1     1   0   0    0   1
7   18:59  'b a dog'       1     1   0   0    0   1
8   19:23  'b w lamp'      0     1   0   0    0   0 
9   19:25  'b r cat'       0     1   0   0    0   0")

期望的输出:

    time   a           b      c
1   18:41  b d cat       1     0
2   18:43  b d dog       1     0 
3   18:47  b d lamp      0     0
4   18:51  b s dog       0     0
5   18:52  b k cat       0     0
6   18:57  b c lion      1     1
7   18:59  b a dog       1     1
8   19:23  b w lamp      0     1 
9   19:25  b r cat       0     1

本质上,我正在寻找一种方法来使列 a 的值作为 b 和 c 中标志变量的开/关开关。

这可以在 Excel 中使用关系公式快速完成,但如果存在,我会喜欢一个优雅的基于 R 的解决方案!

为了解决这个问题,我需要结合的技巧(至少在我的理解中)是

  1. 想出一个公式,让它只适用于第一行之外的所有行。
  2. 如果状态没有根据逻辑的前两位更改,请参阅上面的行。

先感谢您。

标签: r

解决方案


读取您的数据并设置除第一行之外的所有列b和:cNA

dd = read.table(header = T, text = "    time   a           b      c
1   18:41  'b d cat'       1     0
2   18:43  'b d dog'       1     0 
3   18:47  'b d lamp'      0     0
4   18:51  'b s dog'       0     0
5   18:52  'b k cat'       0     0
6   18:57  'b c lion'      1     1
7   18:59  'b a dog'       1     1
8   19:23  'b w lamp'      0     1 
9   19:25  'b r cat'       0     1")

dd$b[-1] = NA
dd$c[-1] = NA

dd
#    time        a  b  c
# 1 18:41  b d cat  1  0
# 2 18:43  b d dog NA NA
# 3 18:47 b d lamp NA NA
# 4 18:51  b s dog NA NA
# 5 18:52  b k cat NA NA
# 6 18:57 b c lion NA NA
# 7 18:59  b a dog NA NA
# 8 19:23 b w lamp NA NA
# 9 19:25  b r cat NA NA

我认为以上是起点(将来如果您提供如上所述的复制/可粘贴起点会很好)。

我们将创建一个新列on_off,其中包含查找lamp和的共享逻辑lion

dd$on_off = NA
dd$on_off[c(FALSE, grepl(pattern = "lamp", x = dd$a[-1]))] = 0
dd$on_off[c(FALSE, grepl(pattern = "lion", x = dd$a[-1]))] = 1

然后我们将在搜索字符串时引用该列b或单独引用该列c"\\b"是单词边界的正则表达式模式,这使我们无法匹配,例如"c"in "cat"):

dd$b[-1] = ifelse(grepl("\\bb\\b", dd$a[-1]), dd$on_off[-1], NA)
dd$c[-1] = ifelse(grepl("\\bc\\b", dd$a[-1]), dd$on_off[-1], NA)

最后,我们用之前的观察填充缺失值:

dd$b = zoo::na.locf(dd$b)
dd$c = zoo::na.locf(dd$c)

dd
#    time        a b c on_off
# 1 18:41  b d cat 1 0     NA
# 2 18:43  b d dog 1 0     NA
# 3 18:47 b d lamp 0 0      0
# 4 18:51  b s dog 0 0     NA
# 5 18:52  b k cat 0 0     NA
# 6 18:57 b c lion 1 1      1
# 7 18:59  b a dog 1 1     NA
# 8 19:23 b w lamp 0 1      0
# 9 19:25  b r cat 0 1     NA

您可以使用 删除on_offdd$on_off = NULL。我把它留在里面是为了让事情更清楚一点。


推荐阅读