Функция R apply (), возвращающая список из нескольких элементов - PullRequest
0 голосов
/ 11 февраля 2020

Вот мой входной фрейм данных:

test <- data.frame(Col1=c("A","BCCC","DE"), Col2=c("Z","BC", "DEEEE"))
test
  Col1  Col2
1    A     Z
2 BCCC    BC
3   DE DEEEE

Я пытаюсь создать еще 2 столбца в моем фрейме данных таким образом, чтобы, если строка в Col1 содержалась в строке в Col2 (или наоборот), я обрезаю все общие символы из этих 2 строк и вывожу 2 обрезанные строки в отдельных столбцах, называемых Col1_short и Col2_short (или точками, если они не совпадают):

  Col1  Col2 Col1_short Col2_short
1    A     Z          .          .
2 BCCC    BC        BCC          B
3   DE DEEEE          D       DEEE

Я пытаюсь использовать такой подход, при котором я создаю список списков, которые я мог бы в дальнейшем удалить из списка и добавить к исходному фрейму данных, но он не работает. Кто-нибудь может увидеть исправление или более простой способ сделать это?

Мой код:

out <- apply(
    test,
    1,
    function(x){
        ifelse(
            grepl(test$Col1, test$Col2) || grepl(test$Col2, test$Col1),
            {
                common <- ifelse(
                    nchar(test$Col1) < nchar(test$Col2),
                    nchar(test$Col1) - 1,
                    nchar(test$Col2) - 1
                )

                pattern = paste0(".{", common, "}$")

                return(
                    list(
                        Col1_short=gsub(pattern, "", x[1]),
                        Col2_short=gsub(pattern, "", x[2])
                    )
                )
            },
            return(
                list(
                    Col1_short=".",
                    Col2_short="."
                )
            )
        )
        }
    )

Вывод:

out
[[1]]
[[1]]$Col1_short
[1] "."

[[1]]$Col2_short
[1] "."


[[2]]
[[2]]$Col1_short
[1] "."

[[2]]$Col2_short
[1] "."


[[3]]
[[3]]$Col1_short
[1] "."

[[3]]$Col2_short
[1] "."

Я думал добавить 2 новых столбца к фрейму данных, выполнив:

test$Col1_short <- unlist(out)[attr(unlist(out), "names") == "Col1_short"]
test$Col2_short <- unlist(out)[attr(unlist(out), "names") == "Col2_short"]

Ответы [ 2 ]

2 голосов
/ 11 февраля 2020

Вы можете попробовать код ниже

dfout <-
  cbind(test, `colnames<-`(sapply(test, function(x) {
    z <-
      as.character(x)
    substring(z, 1, nchar(z) - 1)
  }), paste0(names(test), "_short")))

такой, что

> dfout
  Col1  Col2 Col1_short Col2_short
1    A     Z                      
2 BCCC    BC        BCC          B
3   DE DEEEE          D       DEEE
1 голос
/ 11 февраля 2020

Мы можем использовать mapply и проверить Col1 и соответствующее значение Col2.

test[c("Col1_short", "Col2_short")] <- t(mapply(function(x, y) {
    if(grepl(x, y))
       c(substr(x, 1, nchar(x) - 1), substr(y, 1, nchar(y) - 1))
    else if(grepl(y, x))
        c(substr(x, 1, nchar(x) - 1), substr(y, 1, nchar(y) - 1))
    else
        c('.', '.')
}, test$Col1, test$Col2))

test
#  Col1  Col2 Col1_short Col2_short
#1    A     Z          .          .
#2 BCCC    BC        BCC          B
#3   DE DEEEE          D       DEEE

data

Использование stringsAsFactors = FALSE, чтобы иметь символьные столбцы вместо факторов.

test <- data.frame(Col1=c("A","BCCC","DE"), Col2=c("Z","BC", "DEEEE"),
                   stringsAsFactors = FALSE)
...