将频率数据帧转换为更宽的格式
transform a dataframe of frequencies to a wider format
我有一个看起来像这样的数据框。
input dataframe
position,mean_freq,reference,alternative,sample_id
1,0.002,A,C,name1
2,0.04,G,T,name1
3,0.03,A,C,name2
这些数据是假设基因组中给定位置的核苷酸差异,mean_freq
是相对于参考的,所以第一行表示C's
的比例是0.002
暗示A
在 0.998
.
我想通过创建新列将其运行转换为不同的结构,
desired_output
position,G,C,T,A,sampleid
1,0,0.002,0,0.998,name1
2, 0.96,0,0.04,0,name
3,0,0.93,0,0.07,name2
我尝试过这种方法
per_position_full_nt_freq <- function(x){
df <- data.frame(A=0, C=0, G=0, T=0)
idx <- names(df) %in% x$alternative
df[,idx] <- x$mean_freq
idx2 <- names(df) %in% x$reference
df[,idx2] <- 1 - x$mean_freq
df$position <- x$position
df$sampleName <- x$sampleName
return(df)
}
desired_output_dataframe <- per_position_full_nt_freq(input_dataframe)
我运行进入错误
In matrix(value, n, p) :
data length [8905] is not a sub-multiple or multiple of the number of columns
此外,我觉得必须有一个更直观的解决方案,大概可以使用 tidyr
或 dplyr
。
我如何方便地将输入数据帧转换为所需的输出数据帧格式?
谢谢。
一个选项是使用 'G'、'C'、'T'、'A' 列名称创建 0 的 matrix
,match
与原始数据集的列名,使用row/column
索引赋值,然后cbind
与原始数据集的'position'和'sample_id',列
m1 <- matrix(0, ncol=4, nrow=nrow(df1), dimnames = list(NULL, c("G", "C", "T", "A")))
m1[cbind(seq_len(nrow(df1)), match(df1$alternative, colnames(m1)))] <- df1$mean_freq
m1[cbind(seq_len(nrow(df1)), match(df1$reference, colnames(m1)))] <- 0.1 - df1$mean_freq
cbind(df1['position'], m1, df1['sample_id'])
# position G C T A sample_id
#1 1 0.00 0.002 0.00 0.098 name1
#2 2 0.06 0.000 0.04 0.000 name1
#3 3 0.00 0.030 0.00 0.070 name2
以下应该可以解决问题:
library(readr)
library(dplyr)
library(tidyr)
input_df <- read_csv(
'position,mean_freq,reference,alternative,sample_id
1,0.002,A,C,name1
2,0.04,G,T,name1
3,0.03,A,C,name2'
)
input_df %>%
mutate( ref_val = 0.1 -mean_freq) %>%
spread(alternative, mean_freq, fill=0) %>%
spread(reference, ref_val, fill=0) %>%
select( position, G, C, T, A, sample_id )
这里的一个假设是替代项和引用是不同的,否则您将得到两个名称相同但值不同的列。如果需要,您需要在代码开头使用几个命令来处理。
我有一个看起来像这样的数据框。
input dataframe
position,mean_freq,reference,alternative,sample_id
1,0.002,A,C,name1
2,0.04,G,T,name1
3,0.03,A,C,name2
这些数据是假设基因组中给定位置的核苷酸差异,mean_freq
是相对于参考的,所以第一行表示C's
的比例是0.002
暗示A
在 0.998
.
我想通过创建新列将其运行转换为不同的结构,
desired_output
position,G,C,T,A,sampleid
1,0,0.002,0,0.998,name1
2, 0.96,0,0.04,0,name
3,0,0.93,0,0.07,name2
我尝试过这种方法
per_position_full_nt_freq <- function(x){
df <- data.frame(A=0, C=0, G=0, T=0)
idx <- names(df) %in% x$alternative
df[,idx] <- x$mean_freq
idx2 <- names(df) %in% x$reference
df[,idx2] <- 1 - x$mean_freq
df$position <- x$position
df$sampleName <- x$sampleName
return(df)
}
desired_output_dataframe <- per_position_full_nt_freq(input_dataframe)
我运行进入错误
In matrix(value, n, p) :
data length [8905] is not a sub-multiple or multiple of the number of columns
此外,我觉得必须有一个更直观的解决方案,大概可以使用 tidyr
或 dplyr
。
我如何方便地将输入数据帧转换为所需的输出数据帧格式?
谢谢。
一个选项是使用 'G'、'C'、'T'、'A' 列名称创建 0 的 matrix
,match
与原始数据集的列名,使用row/column
索引赋值,然后cbind
与原始数据集的'position'和'sample_id',列
m1 <- matrix(0, ncol=4, nrow=nrow(df1), dimnames = list(NULL, c("G", "C", "T", "A")))
m1[cbind(seq_len(nrow(df1)), match(df1$alternative, colnames(m1)))] <- df1$mean_freq
m1[cbind(seq_len(nrow(df1)), match(df1$reference, colnames(m1)))] <- 0.1 - df1$mean_freq
cbind(df1['position'], m1, df1['sample_id'])
# position G C T A sample_id
#1 1 0.00 0.002 0.00 0.098 name1
#2 2 0.06 0.000 0.04 0.000 name1
#3 3 0.00 0.030 0.00 0.070 name2
以下应该可以解决问题:
library(readr)
library(dplyr)
library(tidyr)
input_df <- read_csv(
'position,mean_freq,reference,alternative,sample_id
1,0.002,A,C,name1
2,0.04,G,T,name1
3,0.03,A,C,name2'
)
input_df %>%
mutate( ref_val = 0.1 -mean_freq) %>%
spread(alternative, mean_freq, fill=0) %>%
spread(reference, ref_val, fill=0) %>%
select( position, G, C, T, A, sample_id )
这里的一个假设是替代项和引用是不同的,否则您将得到两个名称相同但值不同的列。如果需要,您需要在代码开头使用几个命令来处理。