【问题标题】:R: expand sequence of binary values from two columnsR:从两列扩展二进制值序列
【发布时间】:2020-12-02 17:06:21
【问题描述】:

我有一个非常复杂的数据集。但为了简单起见,我将使用这些数据。假设我们有这些数据,一列 X 显示不同范围内的数字,另一列是二进制 0/1。我想将二进制 0/1 的序列扩大 1。这将在原始 X 和二进制列中创建新的更长的列(newX,newbinary)。

  X    binary
1 1    1
2 3    0
3 5    0
4 6    1
5 8    1
6 10   0

我想在这里展开 X 列并将二进制值放在它旁边。类似的,

   newX    newbinary
1   1       1
2   2       1
3   3       0
4   4       0
5   5       0
6   6       1
7   7       1
8   8       1
9   9       1
10  10      0

我的尝试是这样的,首先我创建了新的 X 列(扩展了 X)。

   newX <- seq(X[1], X[length])

然后,我使用 for 循环遍历 newX,然后将值与 X 进行比较以检查它是否等于或小于该值。如果 newX[i] 不等于 X[i],则放入之前的二进制值,否则放入 binary[i]。

    for (i in 1:newX[length])
  {
    newbinary= ifelse((newX != X)&(between(newX[i], X[i],X[j+1])), lag(binary), binary)
   }

但这不起作用,给我这个,

   newX    newbinary
  1 1         1
  2 2        NA
  3 3        NA
  4 4        NA
  5 5        NA
  6 6        NA

我真的不知道 newX 列(较长的一列)将如何遍历 X(较短的一列)并相应地放置值。

如何在 R 中实现这一点?

【问题讨论】:

    标签: r dataframe binary


    【解决方案1】:

    尝试使用tidyverse 方法为序列创建数据框,然后使用left_join(),最后使用fill() 来完成二进制变量:

    library(dplyr)
    library(tidyr)
    #Code
    newdf <- data.frame(X=seq(min(df$X),max(df$X),by=1)) %>%
      left_join(df) %>%
      fill(binary)
    

    输出:

        X binary
    1   1      1
    2   2      1
    3   3      0
    4   4      0
    5   5      0
    6   6      1
    7   7      1
    8   8      1
    9   9      1
    10 10      0
    

    使用的一些数据:

    #Data
    df <- structure(list(X = c(1L, 3L, 5L, 6L, 8L, 10L), binary = c(1L, 
    0L, 0L, 1L, 1L, 0L)), class = "data.frame", row.names = c("1", 
    "2", "3", "4", "5", "6"))
    

    【讨论】:

    • 谢谢!这不适用于我的数据。原始数据在这里,*.com/questions/65098710/…
    • 这对于简单数据来说看起来不错吧?我收到此错误,错误:xy 没有公共变量时必须提供by
    • @AmalNasir seq() 中有错字,请尝试在其中设置一个值!
    • 其实问题出在left_joint()上。 seq() 给了我想要的序列。
    • 检查变量,加入必须同名!
    【解决方案2】:

    这行得通吗:

    library(dplyr)
    library(tidyr)
    library(purrr)
    df %>% mutate(y = lead(X, default = max(X)+1), newX = map2(X,y-1,`:`)) %>% 
       unnest(newX) %>% mutate(newbinary = binary) %>% select(newX, newbinary)
    # A tibble: 10 x 2
        newX newbinary
       <int>     <dbl>
     1     1         1
     2     2         1
     3     3         0
     4     4         0
     5     5         0
     6     6         1
     7     7         1
     8     8         1
     9     9         1
    10    10         0
    

    使用的数据:

    df
    # A tibble: 6 x 2
          X binary
      <dbl>  <dbl>
    1     1      1
    2     3      0
    3     5      0
    4     6      1
    5     8      1
    6    10      0
    

    【讨论】:

    • 谢谢,我会试试这个。原始的“复杂”数据在这里,*.com/questions/65098710/…
    • 这给了我相同的数据。我只能看到前 10 行,还有 522 行,我怎样才能用 tibble 来查看这里的所有数据?当我查看 df 时,这给了我完全相同的数据。
    • @AmalNasir,您可能需要将整数和小数分开,并使用与上述相同的逻辑处理整数。
    • 我想我不明白,unnest(newX)。我可以在另一个 df 中获取新列吗?
    • @AmalNasir,所以 unnest 用于扩展列表列。
    【解决方案3】:

    假设数据框在最后的注释中可重现地显示,以下单线性使用read.zoo 将其转换为 zoo 对象,并同时将其转换为 ts 对象扩展它。然后它使用 na.locf 填充 NA 并使用 fortify.zoo 将其转换为 data.frame。将数据框中的名称设置为原始名称。

    library(zoo)
    setNames(fortify.zoo(na.locf(as.ts(read.zoo(DF)))), names(DF))
    

    给予:

        X binary
    1   1      1
    2   2      1
    3   3      0
    4   4      0
    5   5      0
    6   6      1
    7   7      1
    8   8      1
    9   9      1
    10 10      0
    

    上面的单线性也可以写成管道:

    library(zoo)
    library(magrittr)
    
    DF %>%
      read.zoo %>%
      as.ts %>%
      na.locf %>%
      fortify.zoo %>%
      setNames(names(DF))
    

    注意

    Lines <- "
      X    binary
    1 1    1
    2 3    0
    3 5    0
    4 6    1
    5 8    1
    6 10   0"
    DF <- read.table(text = Lines)
    

    【讨论】: