如何整理字符栏?
How to tidy up a character column?
我有:
test_df <- data.frame(isolate=c(1,2,3,4,1,2,3,4,5),label=c(1,1,1,1,2,2,2,2,2),alignment=c("--at","at--","--at","--at","a--","acg","a--","a--", "agg"))
> test_df
isolate label alignment
1 1 1 --at
2 2 1 at--
3 3 1 --at
4 4 1 --at
5 1 2 a--
6 2 2 acg
7 3 2 a--
8 4 2 a--
9 5 2 agg
我想要什么:
我想将对齐字段分解为两列,即位置和字符:
> test_df
isolate label aln_pos aln_char
1 1 1 1 -
2 1 1 2 -
3 1 1 3 a
4 1 1 4 t
...
并非所有比对的长度都相同,但具有相同标签的所有比对都具有相同的长度。
我试过的:
我在想我可以使用 separate
首先让每个位置都有自己的列,然后使用 gather
将这些列变成键值对。但是,我一直没能把单独的部分弄好。
在 base R 中,您可以像这样使用索引和 strsplit
创建列表。
# make variable a character vector
test_df$alignment <- as.character(test_df$alignment)
# get list of individual characters
myList <- strsplit(test_df$alignment, split="")
然后构建 data.frame
# construct data.frame
final_df <- cbind(test_df[rep(seq_len(nrow(test_df)), lengths(myList)),
c("isolate", "label")],
aln_pos=sequence(lengths(myList)),
aln_char=unlist(myList))
在这里,我们采用原始 data.frame 的前两列,并使用 rep
重复这些行,并在其第二个参数中输入一个向量,告诉它重复多少次相应的值它的第一个参数。次数以lengths
计算。 cbind
的第二个参数是对 sequence
的调用,采用相同的 lengths
输出。这会产生从 1 到相应长度的计数。第三个参数是未列出的字符值。
这个returns
head(final_df, 10)
isolate label aln_pos aln_char
1 1 1 1 -
1.1 1 1 2 -
1.2 1 1 3 a
1.3 1 1 4 t
2 2 1 1 a
2.1 2 1 2 t
2.2 2 1 3 -
2.3 2 1 4 -
3 3 1 1 -
3.1 3 1 2 -
既然你提到了tidyr::gather
,你可以试试这个:
test_df <- data.frame(isolate=c(1,2,3,4,1,2,3,4,5),
label=c(1,1,1,1,2,2,2,2,2),
alignment=c("--at","at--","--at","--at","a--","acg","a--","a--", "agg"),
stringsAsFactors = FALSE)
library(tidyverse)
test_df %>%
mutate(alignment = strsplit(alignment,"")) %>%
unnest(alignment)
我有:
test_df <- data.frame(isolate=c(1,2,3,4,1,2,3,4,5),label=c(1,1,1,1,2,2,2,2,2),alignment=c("--at","at--","--at","--at","a--","acg","a--","a--", "agg"))
> test_df
isolate label alignment
1 1 1 --at
2 2 1 at--
3 3 1 --at
4 4 1 --at
5 1 2 a--
6 2 2 acg
7 3 2 a--
8 4 2 a--
9 5 2 agg
我想要什么:
我想将对齐字段分解为两列,即位置和字符:
> test_df
isolate label aln_pos aln_char
1 1 1 1 -
2 1 1 2 -
3 1 1 3 a
4 1 1 4 t
...
并非所有比对的长度都相同,但具有相同标签的所有比对都具有相同的长度。
我试过的:
我在想我可以使用 separate
首先让每个位置都有自己的列,然后使用 gather
将这些列变成键值对。但是,我一直没能把单独的部分弄好。
在 base R 中,您可以像这样使用索引和 strsplit
创建列表。
# make variable a character vector
test_df$alignment <- as.character(test_df$alignment)
# get list of individual characters
myList <- strsplit(test_df$alignment, split="")
然后构建 data.frame
# construct data.frame
final_df <- cbind(test_df[rep(seq_len(nrow(test_df)), lengths(myList)),
c("isolate", "label")],
aln_pos=sequence(lengths(myList)),
aln_char=unlist(myList))
在这里,我们采用原始 data.frame 的前两列,并使用 rep
重复这些行,并在其第二个参数中输入一个向量,告诉它重复多少次相应的值它的第一个参数。次数以lengths
计算。 cbind
的第二个参数是对 sequence
的调用,采用相同的 lengths
输出。这会产生从 1 到相应长度的计数。第三个参数是未列出的字符值。
这个returns
head(final_df, 10)
isolate label aln_pos aln_char
1 1 1 1 -
1.1 1 1 2 -
1.2 1 1 3 a
1.3 1 1 4 t
2 2 1 1 a
2.1 2 1 2 t
2.2 2 1 3 -
2.3 2 1 4 -
3 3 1 1 -
3.1 3 1 2 -
既然你提到了tidyr::gather
,你可以试试这个:
test_df <- data.frame(isolate=c(1,2,3,4,1,2,3,4,5),
label=c(1,1,1,1,2,2,2,2,2),
alignment=c("--at","at--","--at","--at","a--","acg","a--","a--", "agg"),
stringsAsFactors = FALSE)
library(tidyverse)
test_df %>%
mutate(alignment = strsplit(alignment,"")) %>%
unnest(alignment)