Belgilar ustunini to'ldirish va noyob qadriyatlarni topish

Quyidagi tuzilma bilan dataframe bor

test <- data.frame(col = c('a; ff; cc; rr;', 'rr; a; cc; e;'))

Endi dataframe-ni yaratmoqchiman, unda sinov dataframasida har bir noyob qiymat uchun nomlangan ustun bor. Noyob qiymat ';' bilan yakunlangan qiymatdir. belgi va makondan tashqari bo'sh joy bilan boshlanadi. Keyin ustundagi har bir satr uchun qo'g'irchoq ustunlarni 1 yoki 0 bilan to'ldirishni xohlayman.

data.frame(a = c(1,1), ff = c(1,0), cc = c(1,1), rr = c(1,0), e = c(0,1))

  a ff cc rr e
1 1  1  1  1 0
2 1  0  1  1 1

Ichki dlya uchun df yaratish va ustundagi noyob qadriyatlarni ishlatishga harakat qildim, lekin u chalkashliklarga duch kelmoqda. Ustunning noyob qiymatlarini o'z ichiga olgan vektor mavjud. Muammo qanday qilib va ​​nollarni yaratish kerak. grep() bilan ba'zi mutate_all() funktsiyasini sinab ko'rdim, ammo bu ishlamadi.

4
Ikki marta IIRCga rr ega bo'lishingiz kerak.
qo'shib qo'ydi muallif David Arenburg, manba

7 javoblar

qdapTools to'plamlaridan birini olish uchun splitstackshape va mtabulate ya'ni,

library(splitstackshape)
library(qdapTools)

mtabulate(as.data.frame(t(cSplit(test, 'col', sep = ';', 'wide'))))
#   a cc ff rr e
#V1 1  1  1  1 0
#V2 1  1  0  1 1

Bundan tashqari, @ A5C1D2H2I1M1N2O1R2T1 izohlarda qayd etilganidek, splitstackshape

cSplit_e(test, "col", ";", mode = "binary", type = "character", fill = 0)
8
qo'shib qo'ydi
Yaxshi layner.
qo'shib qo'ydi muallif Chirayu Chamoli, manba
Haqiqiy 1-liner cSplit_e (test, "col", ";", mode = "ikkilik", = "belgilar", to'ldirish = 0) :-)
qo'shib qo'ydi muallif A5C1D2H2I1M1N2O1R2T1, manba

Mumkin bo'lgan data.table ilovasi. Birinchidan, biz satrlarni ustunlarga bo'linib, har bir satr uchun voqealarni hisoblashda bir ustunga aylanib, kengroq tarqalamiz

library(data.table)
test2 <- setDT(test)[, tstrsplit(col, "; |;")]
dcast(melt(test2, measure = names(test2)), rowid(variable) ~ value, length)
#    variable a cc e ff rr
# 1:        1 1  1 0  1  1
# 2:        2 1  1 1  0  1
6
qo'shib qo'ydi

Bu erda asosiy R-eritmasi mavjud. Avval bo'sh joyni olib tashlang. Noyob birikmani oling. Haqiqiy ma'lumotlar kvadratini ajratib oling va keyin uning barcha ochilgan qismlari mavjudligini tekshiring. So'ngra, siz osongina raqamga aylantiradigan mantiqiy matritsani olasiz.

test=as.data.frame(apply(test,2,function(x)gsub('\\s+', '',x)))
cols=unique(unlist(strsplit(as.character(test$col), split = ';'))) 
yy=strsplit(as.character(test$col), split = ';') 
z=as.data.frame(do.call.rbind(lapply(yy, function(x) cols %in% x)))
names(z)=cols
z=as.data.frame(lapply(z, as.integer))
3
qo'shib qo'ydi

We can do this with tidyverse

library(tidyverse)
rownames_to_column(test, 'grp') %>%
        separate_rows(col) %>% 
        filter(col!="")  %>% 
        count( grp, col) %>%
        spread(col, n, fill = 0) %>%
        ungroup() %>% 
        select(-grp)
# A tibble: 2 × 5
#      a    cc     e    ff    rr
#*     
#1     1     1     0     1     1
#2     1     1     1     0     1
3
qo'shib qo'ydi

Mana, R yondashuvi:

x   <- strsplit(as.character(test$col), ";\\s?") # split the strings
lvl <- unique(unlist(x))                         # get unique elements
x   <- lapply(x, factor, levels = lvl)           # convert to factor
t(sapply(x, table))                              # count elements and transpose
#     a ff cc rr e
#[1,] 1  1  1  1 0
#[2,] 1  0  1  1 1
3
qo'shib qo'ydi

Another approach with tidytext and tidyverse

library(tidyverse)
library(tidytext) #for unnest_tokens()
df <- test %>%
    unnest_tokens(word, col) %>%
    rownames_to_column(var="row") %>%
    mutate(row = floor(parse_number(row)),
           val = 1) %>%
    spread(word, val, fill = 0) %>%
    select(-row)
df
#    a cc e ff rr
#1   1  1 0  1  1
#2   1  1 1  0  1
3
qo'shib qo'ydi

Hech qanday qo'shimcha paketlarsiz boshqa oddiy echim:

x =  c('a; ff; cc; rr;', 'rr; a; cc; e;')
G = lapply(strsplit(x,';'), trimws)
dict = sort(unique(unlist(G)))
do.call(rbind, lapply(G, function(g) 1*sapply(dict, function(d) d %in% g)))
1
qo'shib qo'ydi