我的问题类似于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中的最后一个值是9999
,500
和1
。现在我想:9999
被5
取代,500
被12
取代,1
被92
取代。所需的输出是:
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))),
但它不起作用。
答案 0 :(得分:3)
这可以使用我在链接问题中发布的几乎相同的解决方案来解决。例如,只需将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
所以添加一些解释:
.I
与row_number()
或1:n()
中的dplyr
或1:nrow(df)
相同,例如基础R中的.N
n()
与dplyr
中的.I[.N]
类似,例如,某个组(或整个数据集)的大小。所以基本上当我按小组运行df
时,我会检索每个小组的最后一行的全局索引 Time
中的行索引,同时使用:=
运算符通过引用将所需值分配给dplyr
。 修改强>
根据OP请求,这里有一个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
解决方案。您的原始解决方案无法正常工作,因为您正在按群组工作,因此您尝试将所有三个值传递给每个组。
我能想到的唯一方法是首先计算组大小,然后取消组合,然后对这些位置的累积总和进行变异,这些行中的某些内容
<body>
<div class="navbar navbar-inverse">
<div class="container-fluid">
<div class="row">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
</div>
<div class="row">
<div class="navbarunder">
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
@Html.Partial("_LoginPartial")
</div>
</div>
</div>
</div>
</div>
<div class="container body-content">
@RenderBody()
<hr />
</div>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
</body>
答案 1 :(得分:3)
使用data.table
的另一种方法是创建另一个 data.table ,其中包含要替换为给定id
的值,然后 join和通过引用更新(同时)。
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
中,加入被视为子集的扩展。考虑在连接上对子集进行的任何操作都很自然。两个操作在某些行上执行某些操作。
对于每个replace$id
,我们在mult = "last"
中找到最后一个匹配的行(df$id
),和 更新该行相应的val
。
v1.9.5
here的安装说明。希望这会有所帮助。