如何在R中的矢量之间进行运行计算

  • 本文关键字:之间 运行 计算 r
  • 更新时间 :
  • 英文 :


我创建了这个数据帧:

Count <- c(1:10)
Give <- c(0,0,5,0,0,5,0,5,0,5)
X <- c(rep(0,10))
Y <- c(rep(0,10))
Z <- c(rep(0,10))
X_Target <- 5
Y_Target <- 10
Z_Target <- 5

基本上,我有3个矢量(X,Y,Z(,每个矢量都有一个目标。我想要一个基于向量Give的X、Y和Z的新计算。一旦Give上的数字大于0,则需要将其添加到Vector X,直到其等于X_Target。然后-计算需要移动到下一个向量(Y(并进行同样的操作,然后移动到下个向量。。。

输出应如下所示:

Count Give X Y  Z
1    0   0 0  0
2    0   0 0  0
3    5   5 0  0
4    0   5 0  0
5    0   5 0  0
6    5   5 5  0
7    0   5 5  0
8    5   5 10 0
9    0   5 10 0
10    5   5 10 5

在这个例子中,我只有3个向量,但请记住,我至少有60个向量,所以我需要它尽可能地自动。

希望我能解释一下自己:(Thnanks!

这很难看,但它给出了所需的结果。


tab1 = data.frame(
Count = c(1:10),
Give = c(0,0,5,0,0,5,0,5,0,5),
X = c(rep(0,10)),
Y = c(rep(0,10)),
Z = c(rep(0,10))
)
targets <- c(5,10,5)
tab2 <- tab1
start <- 2
for(col in 3:ncol(tab2)) {

target <- targets[col-2]



for(row in start:nrow(tab2)) {

if(tab2[row, 2] > 0 & tab2[row, col] < target) {
tab2[row, col] <- pmin(tab2[row - 1, col] + tab2[row, col - 1], target)
} else {
tab2[row, col] <- tab2[row - 1, col]
}

}

start <- which(tab2[, 2] > 0 & tab2[, col] == target)[2]
}
> tab2
Count Give X  Y Z
1      1    0 0  0 0
2      2    0 0  0 0
3      3    5 5  0 0
4      4    0 5  0 0
5      5    0 5  0 0
6      6    5 5  5 0
7      7    0 5  5 0
8      8    5 5 10 0
9      9    0 5 10 0
10    10    5 5 10 5

将其转换为数据帧:

tab1 = data.frame(
Count = c(1:10),
Give =c(0,0,5,0,0,5,0,5,0,5),
X = c(rep(0,10)),
Y = c(rep(0,10)),
Z = c(rep(0,10))
)
# create a list of targets for looping
targets = c(X_Target, Y_Target, Z_Target)

在不使用data.table的情况下,你可以把整个事情放在一个循环中。它会起作用,但要慢得多。

# loop through each column
for(col in seq(1,length(targets))){
print(col)

# loop through each row
for(row in seq(1, dim(tab1[2+col])[1])){

# condition
while(tab1[row,(2+col)] < targets[col] & tab1[row,2]>0){
tab1[row,(2+col)] = tab1[row,(2+col)] +tab1[row,2] 
}
}
}

以下是使用tidyverse进行的其他尝试。

将数据放入长表单中,并通过联接包含目标。

在通过Count的循环中,找到低于目标的给定Count的第一行。对于具有匹配名称(X、Y或Z(的当前行和后续行,添加Give金额。

最后,把结果放回广泛的形式

library(tidyverse)
df <- data.frame(Count, Give, X, Y, Z) %>%
pivot_longer(cols = X:Z) %>%
left_join(data.frame(X_Target, Y_Target, Z_Target) %>%
pivot_longer(cols = everything(), 
names_to = c("name", ".value"), 
names_pattern = "(\w+)_(\w+)")) 
for (i in seq_along(Count)) {
below_target <- min(which(df$Count == i & df$value < df$Target))
name_rows <- which(df$name == df[below_target, "name", drop = T])
rows_to_change <- name_rows[name_rows >= below_target]
df[rows_to_change, "value"] <- df[rows_to_change, "value"] + df[below_target, "Give", drop = T]
}
df %>%
pivot_wider(id_cols = Count)

输出

Count     X     Y     Z
<int> <dbl> <dbl> <dbl>
1     1     0     0     0
2     2     0     0     0
3     3     5     0     0
4     4     5     0     0
5     5     5     0     0
6     6     5     5     0
7     7     5     5     0
8     8     5    10     0
9     9     5    10     0
10    10     5    10     5

我的方法是利用Give的累积和,然后跟踪它是否超过列的目标值。然后打扫一下。

targets <- c(X_Target, Y_Target, Z_Target)
targets_0 <- c(0, targets)
csum_give <- cumsum(Give)
# from cumsum give take off sum of previous targets 
result  <- sapply(1:length(targets), 
function(x) csum_give - sum(targets_0[1:x]))
# Set max value to target max of column
sapply(1:length(targets), 
function(x) result[result[, x] > targets[x], x] <<- targets[x])
# set min value to zero
result[which(result < 0)] <- 0

result
#       [,1] [,2] [,3]
#  [1,]    0    0    0
#  [2,]    0    0    0
#  [3,]    5    0    0
#  [4,]    5    0    0
#  [5,]    5    0    0
#  [6,]    5    5    0
#  [7,]    5    5    0
#  [8,]    5   10    0
#  [9,]    5   10    0
# [10,]    5   10    5

最新更新