【问题标题】:Combine two columns containing lists into single column based on condition根据条件将包含列表的两列合并为一列
【发布时间】:2019-05-28 12:31:20
【问题描述】:

我在数据框中有两列 x 和 y,它们是列表形式的。 col x 中的一些列表具有逻辑(0)值,我想用 y 列中的列表值填充它们。我怎么能在 R 中做到这一点。

样本输入

df <- structure(
  list(
    x = list(
      structure(logical(0), .Dim = c(0L,
                                     2L)),
      structure(
        c(72.8468555473385, 19.1207531432888),
        .Dim = 1:2,
        .Dimnames = list("1", c("X", "Y"))
      ),
      structure(logical(0), .Dim = c(0L, 2L)),
      structure(
        c(72.8466089689375, 19.1222313526198),
        .Dim = 1:2,
        .Dimnames = list("1", c("X", "Y"))
      ),
      structure(
        c(72.8458211528575, 19.1206957620104),
        .Dim = 1:2,
        .Dimnames = list("1", c("X", "Y"))
      )
    ),
    y = list(
      structure(
        c(72.846989997634, 19.1197250026469),
        .Dim = 1:2,
        .Dimnames = list(NULL, c("lon", "lat"))
      ),
      structure(
        c(72.846989997634,
          19.1197250026469),
        .Dim = 1:2,
        .Dimnames = list(NULL, c("lon",
                                 "lat"))
      ),
      structure(
        c(72.8480650003086, 19.1195200000195),
        .Dim = 1:2,
        .Dimnames = list(NULL, c("lon", "lat"))
      ),
      structure(
        c(72.8463200059764,
          19.1207150074423),
        .Dim = 1:2,
        .Dimnames = list(NULL, c("lon",
                                 "lat"))
      ),
      structure(
        c(72.8468350022863, 19.1204500035408),
        .Dim = 1:2,
        .Dimnames = list(NULL, c("lon", "lat"))
      )
    )
  ),
  .Names = c("x", "y"),
  row.names = c(NA,-5L),
  class = "data.frame"
)

我希望 x col 具有来自 x 和 y 的组合值,如下所示

 x
    1 72.84699, 19.11973
    2 72.84686, 19.12075
    3  72.84807, 19.11952
    4 72.84661, 19.12223 
    5 72.84582, 19.12070 

【问题讨论】:

    标签: r list merge


    【解决方案1】:

    可能有更聪明的方法可以做到这一点,但使用基本 R mapply 我们可以检查 lengthx 列,如果它小于 1,那么我们将其替换为 y 列中的值。

    df$x <- mapply(function(x, y) if (length(x) > 1) list(x) else list(y), df$x, df$y)
    
    df
    #                   x                  y
    #1 72.84699, 19.11973 72.84699, 19.11973
    #2 72.84686, 19.12075 72.84699, 19.11973
    #3 72.84807, 19.11952 72.84807, 19.11952
    #4 72.84661, 19.12223 72.84632, 19.12072
    #5 72.84582, 19.12070 72.84684, 19.12045
    

    【讨论】:

      【解决方案2】:

      我们可以在base R 中通过创建逻辑索引来分配“x”列中的值,从而以矢量化方式完成此操作

      i1 <- !lengths(df$x)
      df$x[i1] <- df$y[i1]
      

      或者单行

      df$x <- replace(df$x, i1, df$y[i1])
      df 
      #                x                  y
      #1 72.84699, 19.11973 72.84699, 19.11973
      #2 72.84686, 19.12075 72.84699, 19.11973
      #3 72.84807, 19.11952 72.84807, 19.11952
      #4 72.84661, 19.12223 72.84632, 19.12072
      #5 72.84582, 19.12070 72.84684, 19.12045
      

      tidyverse

      library(tidyverse)
      df %>%
          mutate(x = ifelse(lengths(x)==0, y, x))
      

      基准测试

      在稍微大的数据集上进行一些基准测试

      df1 <- df[rep(seq_len(nrow(df)), 1e6), ]
      df2 <- copy(df1)
      system.time({
      df1$x <- mapply(function(x, y) if (length(x) > 1) list(x) else list(y), df1$x, df1$y)
      
      })
      #user  system elapsed 
      #  6.261   0.941   7.164 
      
      system.time({
      i1 <- !lengths(df2$x)
      df2$x[i1] <- df2$y[i1]
      
      })
      # user  system elapsed 
      #  0.858   0.018   0.874 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多