【问题标题】:If statements and Dates如果语句和日期
【发布时间】:2018-11-19 02:45:16
【问题描述】:

我想要实现的是分配一个带有随时间变化的变量的新列。 它只是其中一个正在改变,所以我想做的是在(日期)之后放置 40,而不是 22

我目前有这个无法正常工作的代码

Idea:
    if(lst$taskDate <= as.Date("2018-11-18")){
    t2$Budget <- case_when(
        t2$taskStaffName == "L" ~ 20,
        t2$taskStaffName == "J" ~ 22,
        TRUE ~ 40
    )
    }else{
        if(lst$taskDate >= as.Date("2018-11-19"))
    t2$Budget <- case_when(
        t2$taskStaffName == "L" ~ 20,
        t2$taskStaffName == "J" ~ 40,
                TRUE ~ 40

    )
        }


This is the Data Sample:

# A tibble: 3,692 x 4
   taskStaffName taskDate   taskMinutes taskBillable
   <chr>         <date>     <chr>       <chr>       
 1 G             2018-07-02 300         true        
 2 G             2018-07-02 180         true        
 3 L             2018-07-02 300         true        
 4 L             2018-07-02 180         false       
 5 C             2018-07-02 360         false       
 6 C             2018-07-02 120         false       
 7 G             2018-07-03 480         true        
 8 L             2018-07-03 30          true        
 9 L             2018-07-03 180         true        
10 L             2018-07-02 30          true        
# ... with 3,682 more rows



Desired Outcome:

# A tibble: 3,692 x 5
   taskStaffName taskDate   taskMinutes taskBillable Budget
   <chr>         <date>     <chr>       <chr>         <dbl>
 1 J             2018-07-02 300         true             22
 2 J             2018-07-02 180         true             22
 3 L             2018-07-02 300         true             20
 4 L             2018-07-02 180         false            20
 5 C             2018-07-02 360         false            40
 6 C             2018-07-02 120         false            40
 7 L             2018-07-03 480         true             20
 8 L             2018-07-03 30          true             20
 9 J             2018-11-19 180         true             40
10 J             2018-11-19 30          true             40
# ... with 3,682 more rows

【问题讨论】:

  • 我不明白您为什么要尝试将ifcase_when 结合起来。为什么不只做一个case_whencase_when(t2$taskStaffName == "L" ~ 20, t2$taskStaffName == "J" &amp; lst$taskDate &lt;= as.Date("2018-11-18") ~ 22, TRUE ~ 40) 如果你真的想嵌套,将case_when 嵌套在case_when 中。或使用ifelseif() 没有向量化,如果你给它一整列,它只会检查顶行。
  • 感谢您让我知道我的错误。仍在学习,这只是我想到的想法,我感谢任何建设性的批评,一直在学习 R。谢谢。如果你能给我更多关于如何完成这项工作的详细信息,我将不胜感激。
  • 我想我写得很详细。我只是没有在我的代码前面写lst$Budget =。这里有一点点补充:lst$Budget = case_when(t2$taskStaffName == "L" ~ 20, t2$taskStaffName == "J" &amp; lst$taskDate &lt;= as.Date("2018-11-18") ~ 22, TRUE ~ 40) 据我所知应该这样做。如果您以复制/可粘贴的方式共享数据(例如,与dput())共享数据,我将对其进行测试。虽然现在我看到它,但我对您的数据感到困惑 - 您只显示一个输入数据框,但您使用 t2lst 就好像你有两个数据框 - 我不知道哪个是哪个...
  • 代码有效。然而,正在做的是将该日期之后的所有预算更改为 40,而不是我需要的 J。你知道我该如何解决这个问题吗?
  • TRUE ~ ... 确定在不满足上述条件时会发生什么。我刚刚从您的代码中复制了TRUE ~ 40 - 我认为这就是您想要的。如果您希望在这种情况下不修改预算数字,请执行TRUE ~ lst$Budget

标签: r date if-statement


【解决方案1】:

推断每个taskStaffName 将有不同的前后费率,因此最好重新考虑如何解决问题。不要使用包含名称和日期的每个组合的case_when(或更糟的是ifelse),而是合并到一个包含前/后费率的框架中并使用适当的字段。

x <- read.table(header=TRUE, stringsAsFactors=FALSE, text="
   taskStaffName taskDate   taskMinutes taskBillable
 1 G             2018-07-02 300         true        
 2 G             2018-07-02 180         true        
 3 L             2018-07-02 300         true        
 4 L             2018-07-02 180         false       
 5 C             2018-07-02 360         false       
 6 C             2018-07-02 120         false       
 7 G             2018-07-03 480         true        
 8 L             2018-07-03 30          true        
 9 L             2018-07-03 180         true        
10 L             2018-07-02 30          true        ")
x$taskDate <- as.Date(x$taskDate)

library(dplyr)
# library(tibble)
taskRates <- tibble::tribble(
  ~taskStaffName, ~before, ~after
 ,"J"           ,      22,     40
 ,"L"           ,      20,     20
 ,"G"           ,      20,     41
 ,"C"           ,      40,     41
)

cutoffDate <- as.Date("2018-11-18")
x %>%
  left_join(taskRates, by = "taskStaffName") %>%
  mutate(Budget = if_else(taskDate <= cutoffDate, before, after)) %>%
  select(-before, -after)
#    taskStaffName   taskDate taskMinutes taskBillable Budget
# 1              G 2018-07-02         300         true     20
# 2              G 2018-07-02         180         true     20
# 3              L 2018-07-02         300         true     20
# 4              L 2018-07-02         180        false     20
# 5              C 2018-07-02         360        false     40
# 6              C 2018-07-02         120        false     40
# 7              G 2018-07-03         480         true     20
# 8              L 2018-07-03          30         true     20
# 9              L 2018-07-03         180         true     20
# 10             L 2018-07-02          30         true     20

这很难假设一个有趣的截止日期。如果您计划制定一个多月的时间表费率,那么可能应该重新审视这个问题,因为使用条件连接(例如,范围连接、模糊连接)可能会更好.参考:


编辑

如果您的逻辑永远不会比 1 个用户更改日期更复杂,那么您可以使用 @Gregor 之前推荐的 case_when 逻辑:

x %>%
  mutate(
    Budget = case_when(
      taskStaffName == "L"     ~ 20,
      taskStaffName == "J" &
        taskDate <= cutoffDate ~ 20,
      TRUE                     ~ 40
    )
  )
#    taskStaffName   taskDate taskMinutes taskBillable Budget
# 1              G 2018-07-02         300         true     40
# 2              G 2018-07-02         180         true     40
# 3              L 2018-07-02         300         true     20
# 4              L 2018-07-02         180        false     20
# 5              C 2018-07-02         360        false     40
# 6              C 2018-07-02         120        false     40
# 7              G 2018-07-03         480         true     40
# 8              L 2018-07-03          30         true     20
# 9              L 2018-07-03         180         true     20
# 10             L 2018-07-02          30         true     20

【讨论】:

  • 有很多名字,一个一个去几乎是浪费时间,你有什么诀窍可以只改变 L 20 J 40 其余的 40 吗?
  • 您需要更具体。听起来您只有一种特殊情况,L=20,其他所有情况均为 40,但基于将其添加到您的原始问题中,我不确定。
  • 所以,L 是 20 J 是 20,其余的都是 40。但是在那之后 J 变为 40,其余的保持原样
  • 感谢您的帮助!我通过下面的一些编码完成了它。不过,我很感激你的时间!
【解决方案2】:

正如 Gregor 提到的,我只是使用 case_when 来解决这个问题。

我最终使用以下代码:

lst2$Budget <- case_when(
    lst$taskStaffName == "L"  ~ 20,
    lst$taskStaffName == "J" & lst$taskDate <= as.Date("2018-11-18") ~ 22,
    lst$taskStaffName == "J" & lst$taskDate > as.Date("2018-11-18") ~ 40,
    TRUE ~ 40
)

感谢大家抽出时间尝试解决我的问题!

【讨论】:

    猜你喜欢
    • 2023-03-14
    • 1970-01-01
    • 2012-09-19
    • 1970-01-01
    • 2011-01-07
    • 2017-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多