Объединить два столбца, содержащих списки, в один столбец на основе условия - PullRequest
0 голосов
/ 01 января 2019

У меня есть два столбца x и y во фрейме данных, которые находятся в форме списка.Некоторые списки в столбце x имеют логическое (0) значение, и я хочу заполнить их значениями из столбца y.Как я могу это сделать в R. enter image description here

Образец dput

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 

Ответы [ 2 ]

0 голосов
/ 01 января 2019

Мы можем сделать это векторизованным способом в 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 
0 голосов
/ 01 января 2019

Возможно, есть более разумный способ сделать это, но, используя базовую R mapply, мы можем проверить столбец length из x, и если он меньше 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...