добавить столбец с индивидуальными результатами - PullRequest
0 голосов
/ 29 ноября 2018

Ниже приведен набор данных, который у меня есть.

Name  Price  
A      3     
A      0.5
A      0.8   
A      0.1
A      0.1  
B      0.5
B      0.9
B      1 
B      0.4
B      5

Мне нужен столбец, который сообщает, что если сумма цен больше 1, то оставьте ее как есть, или же суммируйте ее до следующих цен, пока она не достигнет 1. Мне нужен результаткак показано ниже

Name  Price   Result
A      3      3
A      0.5
A      0.8   1.3 #(Since the below price is 0.1 and 1.3+0.1 is 1.4, 
A      0.1        #can we set a limit)
A      0.1   0.2 
B      0.5
B      0.9   1.4
B      1     1
B      0.4   
B      5     5.4

Ответы [ 3 ]

0 голосов
/ 29 ноября 2018

Вот решение с ave, используемое для разделения данных по группам Name.

df1$Result <- ave(df1$Price, df1$Name, FUN = function(x){
  y <- rep(NA, length(x))
  z <- 0
  for(i in seq_along(x)){
    z <- z + x[i]
    if(z >= 1) {
      y[i] <- z
      z <- 0
    }
  }
  if(z > 0) y[length(x)] <- z
  y
})

df1
#   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    0.0

Данные.

df1 <- read.table(text = "
Name  Price  
A      3     
A      0.5
A      0.8   
A      0.1
A      0.1  
B      0.5
B      0.9
B      1 
B      0.4
B      5
", header = TRUE)
0 голосов
/ 29 ноября 2018

Если вы хотите манипулировать данными с помощью сгруппированных категориальных переменных, попробуйте tapply() или aggregate().

Result <- tapply(df$Price, df$Name, function(x){
  temp <- x
  for(i in 1:(length(x)-1)){
    if(temp[i] < 1){
      temp[i] <- NA
      temp[i + 1] <- x[i + 1] + x[i]
    }
  }
  return(temp)
})

df$Result <- unlist(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   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
0 голосов
/ 29 ноября 2018

Возможно, есть лучший способ решить эту проблему с использованием векторизованных методов 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...