Возможно, есть лучший способ решить эту проблему с использованием векторизованных методов R, но здесь есть традиционный for
цикл
#Initialise values
df$Result <- NA #to store results
sum_vec <- 0 #variable to store carry over values
is_full <- TRUE #flag to check if there is a carryover from previous value
for(i in 1:nrow(df)) { #For each row of the dataframe
if(df$Price[i] >= 1 & is_full) { #if price is greater than 1 and no carryover
df$Result[i] = df$Price[i] #assign current price to result
is_full = TRUE #assign carryover as TRUE
}
else {
sum_vec = sum_vec + df$Price[i] #Add previous value to current price
if (sum_vec >= 1) { #If sum is greater than 1 add it to result
df$Result[i] = sum_vec
is_full = TRUE
sum_vec = 0 #reassign carryover value to 0
}
else {
df$Result[i] = NA #make current result as NA
is_full = FALSE #keep carryover flag as FALSE
}
}
}
df
# Name Price Result
#1 A 3.0 3.0
#2 A 0.5 NA
#3 A 0.8 1.3
#4 A 0.1 NA
#5 A 2.0 2.1
#6 B 0.5 NA
#7 B 0.9 1.4
#8 B 1.0 1.0
#9 B 0.4 NA
#10 B 5.0 5.4
Для обновленного примера мы можем split
по группам (Name
) и примените то же самое снова
df$Result <- unlist(lapply(split(df$Price, df$Name), function(x) {
result <- numeric(length = length(x))
sum_vec <- 0
is_full <- TRUE
for (i in 1:length(x)) {
sum_vec = sum_vec + x[i]
if (sum_vec >= 1 | i ==length(x)) {
result[i] = sum_vec
is_full = TRUE
sum_vec = 0
}
else {
result[i] = NA
is_full = FALSE
}
}
result
}))
df
# Name Price Result
#1 A 3.0 3.0
#2 A 0.5 NA
#3 A 0.8 1.3
#4 A 0.1 NA
#5 A 0.1 0.2
#6 B 0.5 NA
#7 B 0.9 1.4
#8 B 1.0 1.0
#9 B 0.4 NA
#10 B 5.0 5.4