我有这样的df
:
df <- data.frame(FOO = c('A|B|C', 'A|B', 'B|C', 'A', 'C'))
> df
FOO
1 A|B|C
2 A|B
3 B|C
4 A
5 C
我想要一个这样的输出:
> df
X1 X2 X3
1 A B C
2 A B
3 B C
4 A
5 C
到目前为止,我尝试使用以下示例:Split column at delimiter in data frame,但它不会在不重复值的情况下拆分列,我得到的是:
df <- data.frame(do.call('rbind', strsplit(as.character(df$FOO),'|',fixed=TRUE)))
> df
X1 X2 X3
1 A B C
2 A B A
3 B C B
4 A A A
5 C C C
我也收到此警告:
警告消息:在rbind(c(“ A”,“ B”,“ C”),c(“ A”,“ B”),c(“ B”,“ C”)中, “ A”,“ C”):结果的列数不是向量的倍数 长度(arg 2)
在这些情况下我该怎么办?最好使用baseR
答案 0 :(得分:9)
只需:
splt <- strsplit(as.character(df$FOO),"\\|")
all_val <- sort(unique(unlist(splt)))
t(sapply(splt,function(x){all_val[!(all_val %in% x)]<-NA;all_val}))
# [,1] [,2] [,3]
#[1,] "A" "B" "C"
#[2,] "A" "B" NA
#[3,] NA "B" "C"
#[4,] "A" NA NA
#[5,] NA NA "C"
数据:
df <- data.frame(FOO = c('A|B|C', 'A|B', 'B|C', 'A', 'C'))
请注意:
我的版本是base::
(不需要库)且一般:
它还可以与:
一起使用df <- data.frame(FOO = c('A|B|C', 'A|B', 'B|C', 'A', 'C', 'B|D|F'))
答案 1 :(得分:6)
忽略了OP要求的base R
解决方案。请尝试@ AndreElrico,@ r.user.05apr或@milan的解决方案。
这可以通过cSplit_e
软件包中的splitstackshape
完成:
library(splitstackshape)
cSplit_e(
data = df,
split.col = "FOO",
sep = "|",
mode = "value",
type = "character",
fill = " ",
drop = TRUE
)
# FOO_A FOO_B FOO_C
#1 A B C
#2 A B
#3 B C
#4 A
#5 C
在以下df的情况下也可以使用(请参见上文OP的注释)。
(df1 <- data.frame(FOO = c('A|B|C', 'A|B', 'B|C', 'A', 'C', 'B|D|F')))
# FOO
#1 A|B|C
#2 A|B
#3 B|C
#4 A
#5 C
#6 B|D|F
cSplit_e(df1, "FOO", "|", "value", "character", TRUE, fill = " ")
# FOO_A FOO_B FOO_C FOO_D FOO_F
#1 A B C
#2 A B
#3 B C
#4 A
#5 C
#6 B D F
答案 2 :(得分:4)
在基数R中:
%macro Create_subset(Row);
data _NULL_;
set T1(firstobs=&row obs=&row.);
CALL SYMPUT("Condition", Cond);
run;
data Subset_&row.;
set T1;
%qsysfunc(dequote(&Condition.));
applied_cond = &Condition.;
run;
%mend Create_subset;
data _NULL_;
set T1;
call execute('%nrstr(%Create_subset('||strip(_N_)|| '))');
run;
答案 3 :(得分:2)
使用unique
和strsplit
查找所有唯一值(在这种情况下为A
,B
和C
)。使用grep
搜索唯一值,并在匹配时返回值,否则返回character(0)
。 cbind
得到的字符。使用apply
和ifelse
将character(0)
替换为NA
。
vals <- unique(unlist(sapply(a1, function(x) strsplit(x, '|', fixed = T))))
out <- NULL
for(i in vals){
out <- cbind(out, as.character((lapply(df$FOO, function(x) grep(x, i, value=T)))))
}
apply(out, 2, function(x) ifelse(x=="character(0)", NA, x))
[,1] [,2] [,3]
[1,] "A" "B" "C"
[2,] "A" "B" NA
[3,] NA "B" "C"
[4,] "A" NA NA
[5,] NA NA "C"
答案 4 :(得分:0)
您也可以尝试使用tidyverse
library(tidyverse)
df %>%
rownames_to_column() %>%
separate_rows(FOO, sep="[|]") %>%
mutate(L=factor(FOO, labels = paste0("X",1:length(unique(FOO))))) %>%
spread(L, FOO) %>%
select(-1)
X1 X2 X3
1 A B C
2 A B <NA>
3 <NA> B C
4 A <NA> <NA>
5 <NA> <NA> C
它通常也可以正常工作df <- data.frame(FOO = c('A|B|C', 'A|B', 'B|C', 'A', 'C', 'B|D|F'))
。此外,您可以设置级别,例如B> C> A自己使用mutate步骤中的factor函数中的levels = c("B", "C", "A")
。