【问题标题】:R : Create new column with the difference between values from the same column where one of them match a conditionR:创建新列,其中一个与条件匹配的同一列中的值之间的差异
【发布时间】:2019-10-11 14:37:31
【问题描述】:

我有一个包含以下列的数据框:Slot、Period、SortNumber 和 Value。 实际上,这个数据框是从一些访问数据库中读取数据而创建的,我在比较字符串等方面做了一些工作......所以,我也使用 RODBC 和 stringr 包。这部分代码在 R 和 Power BI 中完美运行,所以,我没有在这里重现。 这是我的最终数据框的示例:

dfAccess <- data.frame(Slot = c("X1", "X2", "X3", "X1", "X3","X1", "X2", "X3", "X2", "X3"), 
                       Period = c(1,1,1,2,2,1,1,1,2,2), 
                       SortNumber = c(1, 1, 1, 1,1,2,2,2,2,2), 
                       Value = c(9,5,7,9,5,6,4,8,2,1))

此数据帧在 SortNumber 1 中没有时段 2 的 Slot X2,也没有 SortNumber 2 中时段 2 的 Slot X1(它可以错过任何行)。在视觉上,它意味着:

Slot     Period    SortNumber    Value    
=======================================
X1         1          1           9    
X2         1          1           5    
X3         1          1           7    
X1         2          1           9   
X3         2          1           5    
X1         1          2           6    
X2         1          2           4    
X3         1          2           8    
X2         2          2           2    
X3         2          2           1    

我想创建一个新列 (DiffValue) 来计算 Value 和 Value 之间的差异,其中 SortNumer 为 = 1(按 Slot 和 Period 分组)

问题是 Slot 和 Period 不一定对每个 SortNumber 都具有相同的值。在这种情况下,我想使用 0 作为默认值并计算每一行的差异。

我正在使用dplyr,当数据一致时,工作正常。否则,我会收到错误消息:"Column DiffValue must be length 1 (the group size), not 0"

  dfAccess <-dfAccess %>%
  group_by(Slot, Period) %>%
  mutate(DiffValue = Value - Value[SortNumber == 1] )

使用这些数据,我希望看到的是:

Slot     Period    SortNumber    Value    DiffValue
=========================================================
X1         1          1           9            0
X2         1          1           5            0
X3         1          1           7            0
X1         2          1           9            0
X3         2          1           5            0
X1         1          2           6           -3
X2         1          2           4           -1
X3         1          2           8            1
X2         2          2           2           -2 ("0" - 2)
X3         2          2           1           -4

这是一种方法吗?

编辑:我修改了原始帖子的部分内容,因为 Sinh Nguyen 发现了数据中的问题,但我仍然无法计算差异。

谢谢!

【问题讨论】:

  • 我认为错误出在您的实际数据中。至少一对Slot+Period 没有任何SortNumber==1。从错误输出中,我猜这对只有一条记录 SortNumber!=1
  • @SinhNguyen,你是完全正确的。 SortNumber 1 比 SortNumber 2 多一排。我为我的错道歉。但是,它带来了一个我没想到的条件......如果 Slot 和 Period 没有相同的值。假设缺失行的值为 0,有没有办法计算差异?

标签: r dplyr powerbi


【解决方案1】:

仍然不能完全确定您的数据集的性质以及您想要实现的目标。但这将解决错误,对于没有SortNumber==1 的一对Slot+Period,它将自动使用0(Zero) 作为默认值。

# Sample data set with one pair of Slot+Period that doesn't have any SortNumber==1
dfAccess <- data.frame(Slot = c("X1", "X2", "X3", "X1", "X2", "X3","X1", "X2", "X3","X1", "X2", "X3"), 
           Period = c(1,1,1,2,2,2,1,1,1,2,2,2), 
           SortNumber = c(1, 1, 2, 1,1,1,2,2,2,2,2,2), 
           Value = c(9,5,7,9,1,5,6,4,8,10,2,1))

# Your command will generate an error
dfAccess <-dfAccess %>%
      group_by(Slot, Period) %>%
      mutate(DiffValue = Value - Value[SortNumber == 1] )
# ​Error: Column `DiffValue` must be length 2 (the group size) or one, not 0

# This command will only take 1st value of SortNumber==1 in any pair Slot+Number
dfAccess %>%
    group_by(Slot, Period) %>%
    mutate(DiffValue = Value - first(Value[SortNumber==1], default=0)) %>%
    ungroup()

【讨论】:

    【解决方案2】:

    不确定我是否理解正确,但作为练习,我将您的数据框转换为更宽的格式,以便更容易查看:

    df <- dfAccess %>%
      filter(SortNumber == 1) %>% 
      full_join(
        dfAccess %>% 
          filter(SortNumber == 2),
        by= c("Slot", "Period")
      ) %>% 
      mutate_at(vars(Value.x, Value.y), replace_na, 0) %>%    # impute missing values with zero
      rowwise() %>% 
      mutate(
        DiffValue = Value.y - Value.x
      )
    

    df 包含:

    # A tibble: 6 x 7
      Slot  Period SortNumber.x Value.x SortNumber.y Value.y DiffValue
      <fct>  <dbl>        <dbl>   <dbl>        <dbl>   <dbl>     <dbl>
    1 X1         1            1       9            2       6        -3
    2 X2         1            1       5            2       4        -1
    3 X3         1            1       7            2       8         1
    4 X1         2            1       9           NA       0        -9
    5 X3         2            1       5            2       1        -4
    6 X2         2           NA       0            2       2         2
    

    注意第 4 行和第 6 行,其中一个或另一个 SortNumber 缺失。

    可以采用与您要求的格式类似的格式(我的代码很丑,但可以):

    df2 <- df %>% 
      select(1:4) %>% 
      rename(
        SortNumber = 3,
        Value = 4
      ) %>% 
      mutate(
        DiffValue = 0
      ) %>% 
      bind_rows(
        df %>% 
          select(-3, -4) %>% 
          rename(
            SortNumber = 3,
            Value = 4
          )
      )
    

    df2 包含:

    # A tibble: 12 x 5
       Slot  Period SortNumber Value DiffValue
       <fct>  <dbl>      <dbl> <dbl>     <dbl>
     1 X1         1          1     9         0
     2 X2         1          1     5         0
     3 X3         1          1     7         0
     4 X1         2          1     9         0
     5 X3         2          1     5         0
     6 X2         2         NA     0         0
     7 X1         1          2     6        -3
     8 X2         1          2     4        -1
     9 X3         1          2     8         1
    10 X1         2         NA     0        -9
    11 X3         2          2     1        -4
    12 X2         2          2     2         2
    

    如果您不想估算“SortNumber == 2”,那么替代方案是:

    df3 <- dfAccess %>%
      filter(SortNumber == 1) %>% 
      full_join(
        dfAccess %>% 
          filter(SortNumber == 2),
        by= c("Slot", "Period")
      ) %>% 
      mutate_at(vars(Value.x), replace_na, 0) %>% 
      rowwise() %>% 
      mutate(
        DiffValue = Value.y - Value.x
      ) %>% 
      select(1:4) %>% 
      rename(
        SortNumber = 3,
        Value = 4
      ) %>% 
      mutate(
        DiffValue = 0
      ) %>% 
      bind_rows(
        df %>% 
          select(-3, -4) %>% 
          rename(
            SortNumber = 3,
            Value = 4
          )
      ) 
    
    

    df3 将是:

    # A tibble: 12 x 5
       Slot  Period SortNumber Value DiffValue
       <fct>  <dbl>      <dbl> <dbl>     <dbl>
     1 X1         1          1     9         0
     2 X2         1          1     5         0
     3 X3         1          1     7         0
     4 X1         2          1     9         0
     5 X3         2          1     5         0
     6 X2         2         NA     0         0
     7 X1         1          2     6        -3
     8 X2         1          2     4        -1
     9 X3         1          2     8         1
    10 X1         2         NA    NA        NA
    11 X3         2          2     1        -4
    12 X2         2          2     2         2
    

    HTH 或至少为您提供有关如何解决此问题的想法

    【讨论】:

      猜你喜欢
      • 2021-12-26
      • 2019-09-21
      • 1970-01-01
      • 2016-09-27
      • 2018-08-10
      • 1970-01-01
      • 2017-08-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多