【问题标题】:Create boolean column in R dataframe that returns true if another columns value changes row-to-row在 R 数据框中创建布尔列,如果另一个列值逐行更改,则返回 true
【发布时间】:2019-01-16 05:48:13
【问题描述】:

标题很罗嗦,但我的问题很难用一个 sn-p 来解释,所以我准备了一个可重现的例子。以下是我的数据框的一个子集:

> zed
   possessionName possessionMarket
1          Eagles   Boston College
2     Blue Devils             Duke
3            <NA>             <NA>
4     Blue Devils             Duke
5          Eagles   Boston College
6     Blue Devils             Duke
7     Blue Devils             Duke
8          Eagles   Boston College
9          Eagles   Boston College
10         Eagles   Boston College
11           <NA>             <NA>
12    Blue Devils             Duke
13    Blue Devils             Duke
14           <NA>             <NA>
15         Eagles   Boston College

> dput(zed)
structure(list(possessionName = c("Eagles", "Blue Devils", NA, 
"Blue Devils", "Eagles", "Blue Devils", "Blue Devils", "Eagles", 
"Eagles", "Eagles", NA, "Blue Devils", "Blue Devils", NA, "Eagles"
), possessionMarket = c("Boston College", "Duke", NA, "Duke", 
"Boston College", "Duke", "Duke", "Boston College", "Boston College", 
"Boston College", NA, "Duke", "Duke", NA, "Boston College")), class = "data.frame", row.names = c(NA, 
15L))

这是我正在寻找的输出:

> zed
   possessionName possessionMarket outputCol
1          Eagles   Boston College         1
2     Blue Devils             Duke         1
3            <NA>             <NA>         0
4     Blue Devils             Duke         0
5          Eagles   Boston College         1
6     Blue Devils             Duke         1
7     Blue Devils             Duke         0
8          Eagles   Boston College         1
9          Eagles   Boston College         0
10         Eagles   Boston College         0
11           <NA>             <NA>         0
12    Blue Devils             Duke         1
13    Blue Devils             Duke         0
14           <NA>             <NA>         0
15         Eagles   Boston College         1

问题:我希望 newCol 中的第一行为 1。对于所有后续行,如果学校名称从一行更改,我希望值为 == 1到下一个。例如,第 1 行是 Eagles,第 2 行是 Blue Devils,所以第 2 行的 newCol 列中应该有 1。

如果有 ,我希望该行为零。

注意在第 2-4 行,学校名称没有改变,即使有一个 NA,所以第 4 行 == 0。但是,在第 10-12 行中,数据从 Eagles 到 Blue Devils(尽管中间有 NA),所以第 12 行应该是 1。

通常我会这样做:

zed <- zed %>% 
  dplyr::mutate(newCol = ifelse(possessionName[2:length(possessionName)] != possessionName[1:(length(possessionName)-1)], 1, 0))

...但是,由于 NA 的存在,这种方法被挫败了。我有更好的方法来解决这个问题吗?我正在积极解决这个问题,并希望在发布之前发布一个答案,但可以使用一些帮助。提前致谢 !!!

【问题讨论】:

    标签: r dplyr data-manipulation


    【解决方案1】:

    一种方法是使用来自zoona.locf 用以前的NAs 填充NAs 并进行比较

    library(zoo)
    
    zed$possessionName <- na.locf(zed$possessionName)
    zed$output_col <- c(1, +(zed$possessionName[-1] != zed$possessionName[-nrow(zed)]))
    
    
    zed
    #   possessionName possessionMarket output_col
    #1          Eagles   Boston College          1
    #2     Blue Devils             Duke          1
    #3     Blue Devils             <NA>          0
    #4     Blue Devils             Duke          0
    #5          Eagles   Boston College          1
    #6     Blue Devils             Duke          1
    #7     Blue Devils             Duke          0
    #8          Eagles   Boston College          1
    #9          Eagles   Boston College          0
    #10         Eagles   Boston College          0
    #11         Eagles             <NA>          0
    #12    Blue Devils             Duke          1
    #13    Blue Devils             Duke          0
    #14    Blue Devils             <NA>          0
    #15         Eagles   Boston College          1
    

    但由于您使用的是tidyverse,我们可以使用filllag

    library(tidyverse)
    
    zed %>%
      fill(possessionName) %>%
       mutate(output_col = c(1, +(possessionName != lag(possessionName))[-1]))
    

    【讨论】:

    • 哦哇不知道filllag这些看起来很棒,尤其是滞后
    【解决方案2】:

    因此,这可以使用 zoo 包首先摆脱 NA,然后进行逐行比较。

    zed <- zed %>%
        dplyr::mutate(possIdTemp = zoo::na.locf(possessionName)) %>%
        dplyr::mutate(isNewPossession = c(1, ifelse(possIdTemp[2:length(possIdTemp)] != possIdTemp[1:(length(possIdTemp)-1)], 1, 0)))
    

    请我愿意为此提供更好的解决方案,特别是我不喜欢 c(1, ifelse(possIdTemp[2:length(possIdTemp)] != possIdTemp[1:(length(possIdTemp)-1)], 1, 0)) 的代码行 - 谢谢!

    【讨论】:

      猜你喜欢
      • 2019-10-07
      • 2017-12-07
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 2019-02-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多