根据条件代入或求和
Substituting or summing based on condition
我有一个看起来像这样的数据集
df <- data.frame("id" = c("Alpha", "Alpha", "Alpha","Alpha","Beta","Beta","Beta","Beta"),
"Year" = c(1970,1971,1972,1973,1974,1977,1978,1990),
"Group" = c(1,NA,1,NA,NA,2,2,NA),
"Val" = c(2,3,3,5,2,5,3,5))
我想创建一个 "Val" 的累计和。我知道如何做简单的累加和
df <- df %>% group_by(id) %>% mutate(cumval=cumsum(Val))
但是,我希望我的最终数据看起来像这样
final <- data.frame("id" = c("Alpha", "Alpha", "Alpha","Alpha","Beta","Beta","Beta","Beta"),
"Year" = c(1970,1971,1972,1973,1974,1977,1978,1990),
"Group" = c(1,NA,1,NA,NA,2,2,NA),
"Val" = c(2,3,3,5,2,5,3,5),
"cumval" = c(2,5,6,11,2,7,5,10))
基本思路是,当两个 "Val" 相同时 "Group" 晚发生的(年份)替代前一个。
例如,在示例数据集中,观察 3 的 "cumval" 为 6 而不是 8,因为 1972 年的 "Val" 替换了 1970 年的 "Val"。Beta 也是如此。
在此先感谢您的帮助
在我看来,这需要一个 for
循环。首先,我们通过 id
列将数据帧拆分为两个列表。然后我们创建两个空列表。在 og
列表中,我们将放置第一个唯一的非 NA 组标识符所在的行。对于 alpha
这是第一行,对于 Beta
这是第二行。当值被替换时,我们将使用它从累计和中减去。
mylist <- split(df, f = df$id)
og <- list()
vals <- list()
df_num <- 1
我们将使用嵌套循环,外循环遍历列表中的每个对象(在本例中为数据帧),内循环遍历组列中的每个值。
我们需要跟踪行号,这是我们用 r
变量做的。我们最初在 for 循环外将其设置为 0
,因此我们添加了 1
。首先,我们检查我们是否位于数据框的第一行,在这种情况下,累积和等于 Val
列第一行中的值。然后在 if
测试中,我们使用另一个 if
测试来检查组 ID 是否为 NA。如果不是,则这是该数字的第一次出现,如果该数字再次出现,则表示将替换当前值。所以我们把这个数字保存到临时变量temp
。我们还将包含值的行提取并保存到 og
列表。
在此之后,进入下一次迭代。我们检查当前组值是否为 NA。如果是,那么我们只需将该值添加到累计总和。如果它不等于 NA,我们检查该值是否为 NA 并且等于 temp
中存储的值。如果两者都是真的,那么这意味着我们需要替换。我们提取存储在 og
列表中的原始值并将其保存为旧值。然后我们从累积和中减去旧值并添加当前值。我们还将 og
中的原始值替换为当前替换值。这是因为如果需要再次替换该值,我们将需要减去当前值而不是原始值。
如果j
为NA但不等于temp
,那么这是一个新的Group实例。所以我们将具有原始值的行保存到 og
列表中,并保存 Group
。总和继续正常,因为这不是替换值的实例。请注意,用于对 og
列表中的元素进行计数的变量 x
仅在将新出现的元素添加到列表时递增。因此,og[[x-1]]
将始终是替换值。
for (my_df in mylist) {
x <- 1
r <- 0
for (j in my_df$Group) {
r <- r + 1
if (r == 1) {
vals[[1]] <- my_df$Val[1]
if (is.na(j)==FALSE) {
og[[x]] <- df[r, c('Group', 'Val'), drop = FALSE]
temp <- j
x <- x + 1
}
next
}
if (is.na(j)==TRUE) {
vals[[r]] <- vals[[r-1]] + my_df$Val[r]
} else if (is.na(j)==FALSE & j==temp) {
old <- og[[x-1]]
old <- old[,2]
vals[[r]] <- vals[[r-1]] - old + df$Val[r]
og[[x-1]] <- df[r, c('Group', 'Val'), drop = FALSE]
} else {
vals[[r]] <- vals[[r-1]] + my_df$Val[r]
og[[x]] <- my_df[r, c('Group', 'Val')]
temp <- j
x <- x + 1
}
}
cumval <- unlist(vals) %>% as.data.frame()
colnames(cumval) <- 'cumval'
my_df <- cbind(my_df, cumval)
mylist[[df_num]] <- my_df
df_num <- df_num + 1
}
最后,我们通过使用 dplyr
包中的 bind_rows
将它们绑定在行上来组合列表中的两个数据框。然后我用 identical()
检查 Final
数据帧是否与你想要的输出相同,它的计算结果为 TRUE
final_df <- bind_rows(mylist)
identical(final_df, final)
[1] TRUE
我有一个看起来像这样的数据集
df <- data.frame("id" = c("Alpha", "Alpha", "Alpha","Alpha","Beta","Beta","Beta","Beta"),
"Year" = c(1970,1971,1972,1973,1974,1977,1978,1990),
"Group" = c(1,NA,1,NA,NA,2,2,NA),
"Val" = c(2,3,3,5,2,5,3,5))
我想创建一个 "Val" 的累计和。我知道如何做简单的累加和
df <- df %>% group_by(id) %>% mutate(cumval=cumsum(Val))
但是,我希望我的最终数据看起来像这样
final <- data.frame("id" = c("Alpha", "Alpha", "Alpha","Alpha","Beta","Beta","Beta","Beta"),
"Year" = c(1970,1971,1972,1973,1974,1977,1978,1990),
"Group" = c(1,NA,1,NA,NA,2,2,NA),
"Val" = c(2,3,3,5,2,5,3,5),
"cumval" = c(2,5,6,11,2,7,5,10))
基本思路是,当两个 "Val" 相同时 "Group" 晚发生的(年份)替代前一个。 例如,在示例数据集中,观察 3 的 "cumval" 为 6 而不是 8,因为 1972 年的 "Val" 替换了 1970 年的 "Val"。Beta 也是如此。
在此先感谢您的帮助
在我看来,这需要一个 for
循环。首先,我们通过 id
列将数据帧拆分为两个列表。然后我们创建两个空列表。在 og
列表中,我们将放置第一个唯一的非 NA 组标识符所在的行。对于 alpha
这是第一行,对于 Beta
这是第二行。当值被替换时,我们将使用它从累计和中减去。
mylist <- split(df, f = df$id)
og <- list()
vals <- list()
df_num <- 1
我们将使用嵌套循环,外循环遍历列表中的每个对象(在本例中为数据帧),内循环遍历组列中的每个值。
我们需要跟踪行号,这是我们用 r
变量做的。我们最初在 for 循环外将其设置为 0
,因此我们添加了 1
。首先,我们检查我们是否位于数据框的第一行,在这种情况下,累积和等于 Val
列第一行中的值。然后在 if
测试中,我们使用另一个 if
测试来检查组 ID 是否为 NA。如果不是,则这是该数字的第一次出现,如果该数字再次出现,则表示将替换当前值。所以我们把这个数字保存到临时变量temp
。我们还将包含值的行提取并保存到 og
列表。
在此之后,进入下一次迭代。我们检查当前组值是否为 NA。如果是,那么我们只需将该值添加到累计总和。如果它不等于 NA,我们检查该值是否为 NA 并且等于 temp
中存储的值。如果两者都是真的,那么这意味着我们需要替换。我们提取存储在 og
列表中的原始值并将其保存为旧值。然后我们从累积和中减去旧值并添加当前值。我们还将 og
中的原始值替换为当前替换值。这是因为如果需要再次替换该值,我们将需要减去当前值而不是原始值。
如果j
为NA但不等于temp
,那么这是一个新的Group实例。所以我们将具有原始值的行保存到 og
列表中,并保存 Group
。总和继续正常,因为这不是替换值的实例。请注意,用于对 og
列表中的元素进行计数的变量 x
仅在将新出现的元素添加到列表时递增。因此,og[[x-1]]
将始终是替换值。
for (my_df in mylist) {
x <- 1
r <- 0
for (j in my_df$Group) {
r <- r + 1
if (r == 1) {
vals[[1]] <- my_df$Val[1]
if (is.na(j)==FALSE) {
og[[x]] <- df[r, c('Group', 'Val'), drop = FALSE]
temp <- j
x <- x + 1
}
next
}
if (is.na(j)==TRUE) {
vals[[r]] <- vals[[r-1]] + my_df$Val[r]
} else if (is.na(j)==FALSE & j==temp) {
old <- og[[x-1]]
old <- old[,2]
vals[[r]] <- vals[[r-1]] - old + df$Val[r]
og[[x-1]] <- df[r, c('Group', 'Val'), drop = FALSE]
} else {
vals[[r]] <- vals[[r-1]] + my_df$Val[r]
og[[x]] <- my_df[r, c('Group', 'Val')]
temp <- j
x <- x + 1
}
}
cumval <- unlist(vals) %>% as.data.frame()
colnames(cumval) <- 'cumval'
my_df <- cbind(my_df, cumval)
mylist[[df_num]] <- my_df
df_num <- df_num + 1
}
最后,我们通过使用 dplyr
包中的 bind_rows
将它们绑定在行上来组合列表中的两个数据框。然后我用 identical()
检查 Final
数据帧是否与你想要的输出相同,它的计算结果为 TRUE
final_df <- bind_rows(mylist)
identical(final_df, final)
[1] TRUE