如何整理字符栏?

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)