R:将不同长度的列表列表变换为列表向量(作为数据框的一部分)

时间:2016-07-13 20:23:46

标签: r vector dataframe bioinformatics lapply

我有一个csv文件转换为像这样的data.frame( - 是其他不相关的列)

C1    C2     C3    C4    C5    Start     End        C8
A     1      -      -     -    [1,4,7]   [3,6,10]    -
A     2      -      -     -     [12]     [14]        -
A     3      -      -     -     [16,19]  [17,21]     -
A     4      -      -     -     [22]     [24]        -

我打算稍后在迭代开始和结束的每个成员之间的范围内计算。

当然,这种符号对于在Python中进行字面评估很有用,而不是在R中,但是我尝试使用这个函数:

Format the Start and End columns into lists
```{r}
vect <- function(fac){
    str <- as.character(fac)
    return(as.list(strsplit(substr(str,2,nchar(str)-1),",")))
    #return(data.frame(lapply(str, `length<-`, max(lengths(str)))))
}
````

Read in experimental data
```{r}
data <- read.csv("elution_peptides_positions_arath.csv", sep=",",header=TRUE)
data <- mutate(data,Start=vect(Start),End=vect(End))
data$X <- NULL
```

问题在于,它将列表作为列(而不是向量)给出,我不知道为什么!

 > class(data$Start)
[1] "list"

当我尝试将列表转换为带

的向量时
data <- as.data.frame(lapply(data, unlist))

它消除了这个错误:

Error: wrong result size (35676), expected 35568 or 1

我需要它们作为一个向量来应用一个函数来按第一个元素对它们进行排序(我想下面会有效):

id <- order(sapply(data$Start,function(i)i[1])) 
data <- data[order(data$Start),]

但是在列表上这样做会消除此错误:

 Error in order(data_protein$Start) : 
 unimplemented type 'list' in 'orderVector1'

所以我认为我应该将该列转换为矢量。

导致第一个错误的原因是什么?我怎么能解决它?

1 个答案:

答案 0 :(得分:3)

除了两个问题外,您的vect()函数写得很好。首先,您不需要as.list()强制,因为strsplit()始终返回一个列表。其次,你应该将数字从字符强制转换为数字,特别是如果你以后计划用它们进行数字排序。按字典顺序排列的字符串数字不正确。 (另外,在这种情况下,您可以省略return()调用,因为即使没有return(),也会自动返回函数中计算的最终表达式的值,尽管两种方法都有效。)

所以我们有:

vect <- function(fac) {
    str <- as.character(fac);
    lapply(strsplit(substr(str,2L,nchar(str)-1L),','),as.integer);
}; ## end vect()

df$Start <- vect(df$Start);
df$End <- vect(df$End);
df;
##   C1 C2 C3 C4 C5   Start      End C8
## 1  A  1  -  -  - 1, 4, 7 3, 6, 10  -
## 2  A  2  -  -  -      12       14  -
## 3  A  3  -  -  -  16, 19   17, 21  -
## 4  A  4  -  -  -      22       24  -

数据

df <- data.frame(C1=c('A','A','A','A'),C2=c(1L,2L,3L,4L),C3=c('-','-','-','-'),C4=c('-','-',
'-','-'),C5=c('-','-','-','-'),Start=c('[1,4,7]','[12]','[16,19]','[22]'),End=c('[3,6,10]',
'[14]','[17,21]','[24]'),C8=c('-','-','-','-'),stringsAsFactors=F);

您将list列转换为vector的意图存在固有问题。 R data.frame类型强制所有列具有相同的长度。因此,如果您尝试将StartEnd列取消列入原子向量,则它们的长度将超过所有其他列的长度,因此会显示错误消息。

如果您想按照每个Start向量中的第一个数字对data.frame进行排序,那么您的id计算是完美的,尽管可以更加简洁如下:

df[order(sapply(df$Start,`[`,1L)),];
##   C1 C2 C3 C4 C5   Start      End C8
## 1  A  1  -  -  - 1, 4, 7 3, 6, 10  -
## 2  A  2  -  -  -      12       14  -
## 3  A  3  -  -  -  16, 19   17, 21  -
## 4  A  4  -  -  -      22       24  -

(应该注意的是,这个示例data.frame在运行上面的代码行之前已经拥有了相关的顺序。这就是为什么在创建测试数据时考虑test coverage的问题总是好的。 。)