R

时间:2019-03-12 14:11:10

标签: r loops if-statement

我对R中的if语句和循环不是很有经验。

可能您可以帮助我解决我的问题。

我的任务是,如果sum(df $ fz)<450,则将+1添加到df $ fz中,但与此同时,我必须仅将df $ fz中的最大值添加+1,直到sum(( df $ fz)低于450

这是我的df

ID_PP <- c(3,6, 22, 30, 1234456)
z <- c(12325, 21698, 21725, 8378, 18979)
fz <- c(134, 67, 70, 88, 88)

df <- data.frame(ID_PP,z,fz)

对新列df $ new_value进行更改后,其外观应为134 68 71 88 89

此刻我有了这段代码,但是它为所有值添加了+1。

if (sum(df$fz ) < 450) {
  mutate(df, new_value=fz+1)
 }

我知道我可以选择 top_n(3,z)并仅在此顶部添加+1,但这不是我想要的,因为在这种情况下,我必须手动选择一个顶部检查完sum(df $ fz)

1 个答案:

答案 0 :(得分:1)

评论中的说明有所帮助。让我知道这是否适合您。当然,您可以删除cumsum_fzleftover列。

# Making variables to use in the calculation
df <- df %>%
  arrange(fz) %>%
  mutate(cumsum_fz = cumsum(fz),
         leftover = 450 - cumsum_fz)

# Find the minimum, non-negative value to use for select values that need +1
min_pos <- min(df$leftover[df$leftover > 0])

# Creating a vector that adds 1 using the min_pos value and keeps
# the other values the same
df$new_value <- c((head(sort(df$fz), min_pos) + 1), tail(sort(df$fz), length(df$fz) - min_pos))

# Checking the sum of the new value
> sum(df$new_value)
[1] 450
> 
> df
    ID_PP     z  fz cumsum_fz leftover new_value
1       6 21698  67        67      383        68
2      22 21725  70       137      313        71
3      30  8378  88       225      225        89
4 1234456 18979  88       313      137        88
5       3 12325 134       447        3       134

编辑:

因为utubun已经发布了一个很好的tidyverse解决方案,所以我将第一个完全翻译为基础(无论如何将两者混用有点草率)。与上述逻辑相同,并使用提供的数据OP。

 > # Using base
> df <- df[order(fz),]
> 
> leftover <- 450 - cumsum(fz)
> min_pos <- min(leftover[leftover > 0])
> df$new_value <- c((head(sort(df$fz), min_pos) + 1), tail(sort(df$fz), length(df$fz) - min_pos))
> 
> sum(df$new_value)
[1] 450
> df
    ID_PP     z  fz new_value
2       6 21698  67        68
3      22 21725  70        71
4      30  8378  88        89
5 1234456 18979  88        88
1       3 12325 134       134