Как я могу разделить строку символов на столбцы с флагом значения 1/0?
У меня есть вектор символов, например:
a <- c("a,b,c", "a,b", "a,b,c,d")
Что я хотел бы сделать, так это создать фреймворк данных, который выглядит так:
a b c d
1] 1 1 1 0
2] 1 1 0 0
3] 1 1 1 1
У меня такое ощущение, что мне нужно использовать некоторую комбинацию read.table
и reshape
, но я действительно борюсь. Любые и помогают оценить.
Ответы
Ответ 1
Вы можете попробовать cSplit_e
из моего пакета splitstackshape:
library(splitstackshape)
a <- c("a,b,c", "a,b", "a,b,c,d")
cSplit_e(as.data.table(a), "a", ",", type = "character", fill = 0)
# a a_a a_b a_c a_d
# 1: a,b,c 1 1 1 0
# 2: a,b 1 1 0 0
# 3: a,b,c,d 1 1 1 1
cSplit_e(as.data.table(a), "a", ",", type = "character", fill = 0, drop = TRUE)
# a_a a_b a_c a_d
# 1: 1 1 1 0
# 2: 1 1 0 0
# 3: 1 1 1 1
Там также mtabulate
из "qdapTools":
library(qdapTools)
mtabulate(strsplit(a, ","))
# a b c d
# 1 1 1 1 0
# 2 1 1 0 0
# 3 1 1 1 1
Очень прямой подход R основывается на использовании table
вместе с stack
и strsplit
:
table(rev(stack(setNames(strsplit(a, ",", TRUE), seq_along(a)))))
# values
# ind a b c d
# 1 1 1 1 0
# 2 1 1 0 0
# 3 1 1 1 1
Ответ 2
Еще одно свернутое решение base-R:
x <- strsplit(a,",")
xl <- unique(unlist(x))
t(sapply(x,function(z)table(factor(z,levels=xl))))
который дает
a b c d
[1,] 1 1 1 0
[2,] 1 1 0 0
[3,] 1 1 1 1
Ответ 3
Другим вариантом является tstrsplit()
из data.table:
library(data.table)
vapply(tstrsplit(a, ",", fixed = TRUE, fill = 0), ">", integer(length(a)), 0L)
# [,1] [,2] [,3] [,4]
# [1,] 1 1 1 0
# [2,] 1 1 0 0
# [3,] 1 1 1 1
Ответ 4
База R
- но более длинное решение:
el = unique(unlist(strsplit(a, ',')))
do.call(rbind, lapply(a, function(u) setNames(el %in% strsplit(u,',')[[1]]+0L, el))
# a b c d
#[1,] 1 1 1 0
#[2,] 1 1 0 0
#[3,] 1 1 1 1
Ответ 5
После того, как я написал это, я заметил, что решение Colonel Beauvel очень похоже, но, возможно, это достаточно отчетливо, чтобы быть отдельным решением. Пакеты не используются.
Сначала мы разбиваем символьные строки на список векторов L
, а затем вычисляем объединение всех них, u
. Наконец, мы определяем бинарный вектор для каждого элемента списка и rbind
их вместе, преобразуем результат из логического в числовой с помощью + 0
и задаем имена столбцов.
L <- strsplit(a, ",")
u <- Reduce(union, L)
m <- do.call(rbind, lapply(L, `%in%`, x = u)) + 0
colnames(m) <- u
даяние:
> m
a b c d
[1,] 1 1 1 0
[2,] 1 1 0 0
[3,] 1 1 1 1
Добавлено Последние две строки кода можно заменить одним из следующих:
do.call(rbind, lapply(lapply(L, factor, levels = u), table))
do.call(rbind, Map(function(x) sapply(u, `%in%`, x), L)) + 0
Ответ 6
К сожалению, база R не предлагает векторную функцию сопоставления строк, но пакет stringi
делает.
library(stringi)
a=c("a,b,c", "a,b", "a,b,c,d")
1*outer(a,unique(unlist(strsplit(a,","))),stri_detect_regex)
# [,1] [,2] [,3] [,4]
#[1,] 1 1 1 0
#[2,] 1 1 0 0
#[3,] 1 1 1 1