У меня есть следующий фрейм данных, и я пытаюсь разделить запятые и превратить это конкретное имя (имена) в их собственные отдельные столбцы и указать, существуют ли эти конкретные имена столбцов (которые разделены запятыми) для этого конкретного идентификатора. (1 = Да, 0 = Нет) Любая помощь будет принята с благодарностью! Спасибо!
ID<- c(1,2,3,4,5,6)
Details<- c("V1,V2", "V1,V3", "V1", "V2", "V3,V4", "V2,V3" )
data.frame <- data.frame(ID, Details, stringsAsFactors=FALSE)
ЖЕЛАЕМЫЙ РЕЗУЛЬТАТ:
ID<-c(1,2,3,4,5,6)
V1<-c(1,1,1,0,0,0)
V2<-c(1,0,0,1,0,1)
V3<-c(0,1,0,0,1,1)
V4<-c(0,0,0,0,1,0)
data.frame1<-data.frame(ID, V1, V2, V3, V4, stringsAsFactors=FALSE)





Решение с использованием пакета tidyverse. dat - это ваш пример фрейма данных. dat2 - это окончательный фрейм данных.
library(tidyverse)
dat2 <- dat %>%
separate_rows(Details) %>%
mutate(Value = 1L) %>%
spread(Details, Value, fill = 0L)
dat2
# ID V1 V2 V3 V4
# 1 1 1 1 0 0
# 2 2 1 0 1 0
# 3 3 1 0 0 0
# 4 4 0 1 0 0
# 5 5 0 0 1 1
# 6 6 0 1 1 0
Один вариант с mtabulate от qdapTools
library(qdapTools)
cbind.data.frame(ID, # or data.frame$ID
mtabulate(strsplit(as.character(data.frame$Details), ",")))
# output
ID V1 V2 V3 V4
1 1 1 1 0 0
2 2 1 0 1 0
3 3 1 0 0 0
4 4 0 1 0 0
5 5 0 0 1 1
6 6 0 1 1 0
Вот базовое решение R. Я переименовал ваши data.frames в data1 и data2.
data1 <- data.frame(ID, Details, stringsAsFactors=FALSE)
data2 <- data.frame(ID, V1, V2, V3, V4, stringsAsFactors=FALSE)
nms <- unique(unlist(strsplit(data1$Details, ",")))
data3 <- cbind.data.frame(ID, sapply(nms, grepl, data1$Details))
data3[-1] <- lapply(data3[-1], as.integer)
Теперь сравните data3 с ожидаемым результатом data2.
all.equal(data2, data3)
#[1] TRUE
Обратите внимание, однако, что
identical(data2, data3)
#[1] FALSE
Это потому, что я использовал as.integer, а значения в data2 относятся к классу "numeric". Если это имеет значение, вы можете изменить приведенную выше инструкцию lapply, чтобы использовать as.numeric.
используя базу R:
xtabs(val~.,cbind.data.frame(ID=rep(ID,lengths(s<-strsplit(Details,","))),Details=unlist(s),val=1))
Details
ID V1 V2 V3 V4
1 1 1 0 0
2 1 0 1 0
3 1 0 0 0
4 0 1 0 0
5 0 0 1 1
6 0 1 1 0
Самый простой способ, который я вижу, - это создать data.frame для каждого из этих векторов, скрытых в строках, и связать их. purrr может помочь сделать его довольно компактным. Обратите внимание, что столбец ID не нужен, я буду работать непосредственно с Details.
library(purrr)
df <- map_dfr(strsplit(Details, ","),
~data.frame(t(setNames(rep(1, length(.x)), .x))))
df[is.na(df)] <- 0
# V1 V2 V3 V4
# 1 1 1 0 0
# 2 1 0 1 0
# 3 1 0 0 0
# 4 0 1 0 0
# 5 0 0 1 1
# 6 0 1 1 0
Вы также можете разделить и исключить список, чтобы получить различные значения, а затем искать их в исходном векторе:
unique_v <- unique(unlist(strsplit(Details, ",")))
map_dfc(unique_v, ~as.numeric(grepl(.x, Details)))
# # A tibble: 6 x 4
# V1 V2 V3 V4
# <dbl> <dbl> <dbl> <dbl>
# 1 1 1 0 0
# 2 1 0 1 0
# 3 1 0 0 0
# 4 0 1 0 0
# 5 0 0 1 1
# 6 0 1 1 0
Мы могли бы выполнить некоторую оценку грязной строки также, если вы знаете количество столбцов:
m <- as.data.frame(matrix(0,ncol=4,nrow=6))
eval(parse(text=paste0("m[",ID,", c(",gsub("V","",Details),")] <- 1")))
# V1 V2 V3 V4
# 1 1 1 0 0
# 2 1 0 1 0
# 3 1 0 0 0
# 4 0 1 0 0
# 5 0 0 1 1
# 6 0 1 1 0