【问题标题】:Replacing the last value within groups with different values用不同的值替换组中的最后一个值
【发布时间】:2015-10-26 13:21:51
【问题描述】:

我的问题与this post 类似,但不同之处在于不是用全0 替换每个组/id 中的最后一个值,而是使用不同的值替换每个组/id 中的最后一个值。

这是一个例子(我从上面的链接中借来的):

          id  Time
1         1    3
2         1    10
3         1    1
4         1    0
5         1    9999
6         2    0
7         2    9
8         2    500
9         3    0
10        3    1

在上面的链接中,每个组/ID 中的最后一个值被零替换,使用如下:

df %>%
  group_by(id) %>%
  mutate(Time = c(Time[-n()], 0))

输出是

          id  Time
1         1    3
2         1    10
3         1    1
4         1    0
5         1    0
6         2    0
7         2    9
8         2    0
9         3    0
10        3    0

就我而言,我希望将每个组/ID 中的最后一个值替换为不同的值。最初,每个组/ID 中的最后一个值是99995001。现在我想:99995替换,50012替换,192替换。所需的输出是:

          id  Time
1         1    3
2         1    10
3         1    1
4         1    0
5         1    5
6         2    0
7         2    9
8         2    12
9         3    0
10        3    92

我试过这个:

df %>%
  group_by(id) %>%
  mutate(Time = replace(Time, n(), c(5,12,92))),

但它不起作用。

【问题讨论】:

  • 请提供示例数据和代码。 stackoverflow.com/questions/5963269/…
  • 您不能将多个值插入到一个值中。正如@scoa 指出的那样,您应该提供一个可重现的示例和您想要的输出
  • @goren9 你是杰森吗?如果不是,你为什么要重写他的问题?
  • 无论如何,既然问题是有道理的,就投票重新开放。
  • 非常感谢,弗兰克。

标签: r data.table dplyr


【解决方案1】:

这可以使用与我在链接问题中发布的几乎相同的解决方案来解决。例如,只需将 0L 替换为所需的值

library(data.table)
indx <- setDT(df)[, .I[.N], by = id]$V1
df[indx, Time := c(5L, 12L, 92L)]
df
#     id Time
#  1:  1    3
#  2:  1   10
#  3:  1    1
#  4:  1    0
#  5:  1    5
#  6:  2    0
#  7:  2    9
#  8:  2   12
#  9:  3    0
# 10:  3   92

所以补充一些解释:

  1. 对于 未分组 数据,.Idplyr 中的 row_number()1:n() 相同,例如1:nrow(df) 在基础 R 中
  2. .N 类似于dplyr 中的n(),例如,某个组(或整个数据集)的大小。所以基本上当我按组运行.I[.N] 时,我正在检索每个组的最后一行的 global 索引
  3. 下一步就是将此索引用作df 中的行索引,同时使用:= 运算符将所需的值分配给Time通过引用

编辑

根据 OP 的请求,这里有一个可能的 dplyr 解决方案。您的原始解决方案不起作用,因为您是按组工作,因此您试图将所有三个值传递给每个组。

我能想到的唯一方法是首先计算组大小,然后取消组合,然后根据这些位置的累积总和进行变异,这些行中的一些东西

library(dplyr)
df %>%
  group_by(id) %>%
  mutate(indx = n()) %>%
  ungroup() %>%
  mutate(Time = replace(Time, cumsum(unique(indx)), c(5, 12, 92))) %>%
  select(-indx)

# Source: local data frame [10 x 2]
# 
#    id Time
# 1   1    3
# 2   1   10
# 3   1    1
# 4   1    0
# 5   1    5
# 6   2    0
# 7   2    9
# 8   2   12
# 9   3    0
# 10  3   92

【讨论】:

  • 太棒了。太感谢了。我也经常使用“data.table”,但只是出于好奇:如何使用“mutate(Time = replace(Time, n(), c(5,12,92))) 之类的东西来做到这一点?
  • 非常感谢大卫。
【解决方案2】:

使用data.table 的另一种方法是创建另一个data.table,其中包含给定id 要替换的值,然后通过引用加入和更新(同时)。

require(data.table) # v1.9.5+ (for 'on = ' feature)
replace = data.table(id = 1:3, val = c(5L, 12L, 9L)) # from @David
setDT(df)[replace, Time := val, on = "id", mult = "last"]

#     id Time
#  1:  1    3
#  2:  1   10
#  3:  1    1
#  4:  1    0
#  5:  1    5
#  6:  2    0
#  7:  2    9
#  8:  2   12
#  9:  3    0
# 10:  3    9

data.table 中,joins 被视为子集 的扩展。很自然地想到在 subsets 上也对 joins 做任何操作。这两个操作在某些行上做一些事情

对于每个replace$id,我们在df$id 中找到最后一个匹配行(mult = "last"), 更新该行与对应的val

v1.9.5here 的安装说明。希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-30
    • 2021-03-18
    • 1970-01-01
    • 2017-08-14
    相关资源
    最近更新 更多