假设我有一个像这样的变量向量:
>variable
[1] "A1" "A1" "A1" "A1" "A2" "A2" "A2" "A2" "B1" "B1" "B1" "B1"
Run Code Online (Sandbox Code Playgroud)
我想把它转换成这样的数据框:
treatment time
1 A 1
2 A 1
3 A 1
4 A 1
5 A 2
6 A 2
7 A 2
8 A 2
9 B 1
10 B 1
11 B 1
12 B 1
Run Code Online (Sandbox Code Playgroud)
为此,我使用了reshape2的colsplit功能.它需要一个模式来分割字符串,但我很快意识到没有明显的模式来分割两个字符而没有任何空格.我试过""并得到以下结果:
> colsplit(trialm$variable,"",names=c("treatment","time"))
treatment time
1 NA A1
2 NA A1
3 NA A1
4 NA A1
5 NA A2
6 NA A2
7 NA A2
8 NA A2
9 NA B1
10 NA B1
11 NA B1
12 NA B1
Run Code Online (Sandbox Code Playgroud)
我也尝试过lookbehind或lookahead正则表达式:
>colsplit(trialm$variable,"(?<=\\w)",names=c("treatment","time"))
Error in gregexpr("(?<=\\w)", c("A1", "A1", "A1", "A1", "A2", "A2", "A2", :
invalid regular expression '(?<=\w)', reason 'Invalid regexp'
Run Code Online (Sandbox Code Playgroud)
但它给了我上面的错误.我怎么解决这个问题?
A5C*_*2T1 10
沿着这条线的某个地方,"stringr"包(用"reshape2"导入并负责发生的拆分colsplit)开始使用"stringi"来实现它的几个功能.有些行为似乎因此而改变.
使用当前的"reshape2"(和当前的"stringr"包),colsplit按照您对代码的预期方式工作:
packageVersion("reshape2")
## [1] ‘1.4.3’
packageVersion("stringr")
## [1] ‘1.2.0’
colsplit(variable, "", names = c("treatment", "time"))
## treatment time
## 1 A 1
## 2 A 1
## 3 A 1
## 4 A 1
## 5 A 2
## 6 A 2
## 7 A 2
## 8 A 2
## 9 B 1
## 10 B 1
## 11 B 1
## 12 B 1
Run Code Online (Sandbox Code Playgroud)
如果可以在"变量"中检测到模式但是没有可以使用的干净分割字符,那么添加一个:)
library(reshape2)
variable <- c("A1", "A1", "A1", "A1", "A2", "A2",
"A2", "A2", "B1", "B1", "B1", "B1")
## Here, we add a "." between upper case letters and numbers
colsplit(gsub("([A-Z])([0-9])", "\\1\\.\\2", variable),
"\\.", c("Treatment", "Time"))
# Treatment Time
# 1 A 1
# 2 A 1
# 3 A 1
# 4 A 1
# 5 A 2
# ::::: snip :::: #
# 11 B 1
# 12 B 1
Run Code Online (Sandbox Code Playgroud)
我的"splitstackshape"包有一个单用途的非导出辅助函数NoSep,可以用于此:
splitstackshape:::NoSep(variable)
## .var .time_1
## 1 A 1
## 2 A 1
## 3 A 1
## 4 A 1
## 5 A 2
## ::: snip :::: #
## 11 B 1
## 12 B 1
Run Code Online (Sandbox Code Playgroud)
"tidyverse"(特别是"tidyr"包)有几个方便的功能,可以将值分成不同的列:separate和extract.separate也已经被证明jazzuro,但解决方案是非常具体的这方面的问题.此外,它通常使用分隔符更好.extract希望您指定包含要捕获的组的正则表达式:
library(tidyverse)
data.frame(variable) %>%
extract(variable, into = c("Treatment", "Time"), regex = "([A-Z]+)([0-9]+)")
# Treatment Time
# 1 A 1
# 2 A 1
# 3 A 1
# 4 A 1
# 5 A 2
# ::::: snip :::: #
# 11 B 1
# 12 B 1
Run Code Online (Sandbox Code Playgroud)
substr 是另一种方法.
> variable <- c(rep("A1", 4), rep("A2", 4), rep("B1", 4))
> data.frame(treatment=substr(variable, 1,1), time=as.numeric(substr(variable,2,2)))
treatmen time
1 A 1
2 A 1
3 A 1
4 A 1
5 A 2
6 A 2
7 A 2
8 A 2
9 B 1
10 B 1
11 B 1
12 B 1
Run Code Online (Sandbox Code Playgroud)
如果使用向量创建数据框,则variable可以立即separate()从tidyr包中使用.
mydf <- data.frame(variable = c(rep("A1", 4), rep("A2", 4), rep("B1", 4)),
stringsAsFactors = FALSE)
separate(mydf, variable, c("treatement", "time"), sep = 1)
# treatement time
#1 A 1
#2 A 1
#3 A 1
#4 A 1
#5 A 2
#6 A 2
#7 A 2
#8 A 2
#9 B 1
#10 B 1
#11 B 1
#12 B 1
Run Code Online (Sandbox Code Playgroud)
您可以使用substr它来拆分它:
例如
df <- data.frame(treatment = substr(variable, start = 1, stop = 1),
time = substr(variable, start = 2, stop = 2) )
Run Code Online (Sandbox Code Playgroud)