2017-02-22 48 views
0

我具有由R:通过当某些条件满足时,改变另一个值数据集中的除法值

df <- data.frame(
    id = seq(1:9), 
    sample = c("SRM1", "SAM1", "SAM2", "SAM3", "SRM2", "SAM4", "SAM5", "SRM3", "SRM4"), 
    ratio1 = rnorm(9, mean = 2, sd = 0.02), 
    ratio2 = rnorm(9, mean = 1, sd = 0.01)) 

产生的数据集df和看起来像

id sample ratio1 ratio2 
1 SRM1 2.0271 0.99915 
2 SAM1 2.0241 0.98810 
3 SAM2 1.9522 1.00300 
4 SAM3 1.9877 1.00343 
5 SRM2 1.9800 1.00522 
6 SAM4 2.0184 0.97788 
7 SAM5 2.0045 1.00549 
8 SRM3 1.9684 0.99129 
9 SRM4 2.0034 1.00310 

我不得不分割值在ratio1列的SRM列中报告了固定号码a = 1.9。然后,我必须将ratio1列中SAM行中报告的值除以“周围”SRM/a值的平均值。

举一个例子:在id 1和5有两个SRM样本,我计算avg1 <- mean(2.2701, 1.9800)/a。此时我可以计算

df$ratio.corr <- rep(NA, 9) 
df$ratio1.corr[c(2:4)] <- df$ratio1[c(2:4)]/avg1 

对于SAM4SAM5avg2将作为平均的ratio1值的SRM2SRM3样本来计算。

对于假想SAM6id = 10avg3将被计算为报道SRM4ratio1和假想SRM5样品与即id = 11之间的平均。

请考虑以下因素:

  • 真实数据集有大约10000行;
  • avg对于以字符串SRM标识的样本,总是会计算出值;
  • SRM样品有许多不同的名称,没有共同的字符串;从连续SRM
  • 距离可以变化(有时是3,4或甚至0行)也需要
  • 类似的操作为ratio2列,但与b = 0.91代替a

这只是让我发疯。

回答

0

我发现这个可能的解决方案:

library(data.table) 
a = 1.9 
b = 0.91 
df <- as.data.table(df) 

# SRMs 
srm <- grep("SRM", df$sample) 
# SAMs between consecutive SRMs 
sam <- diff(srm)-1 

# Splitting df in SRMs and SAMs 
df.srm <- df[srm][, id := 1:.N] 
df.sam <- df[-srm] 

# For each SAMs I write the IDs of the SRMs before and after it 
srm1 <- rep(df.srm$id[-length(df.srm$id)], sam) 
srm2 <- srm1 + 1 
df.sam <- df.sam[, ':=' (srm1 = srm1, srm2 = srm2)] 

# Calculating ratio1/a and ratio2/b 
df.srm[, ':=' (ratio1.a = ratio1/a, ratio2.b = ratio2/b)] 

# Calculating ratios for each SAMs divided by the average of srm1 and srm2 
df.sam$ratio1.ok <- df.sam$ratio1/((df.srm$ratio1.a[df.sam$srm1] + df.srm$ratio1.a[df.sam$srm2])/2) 
df.sam$ratio2.ok <- df.sam$ratio2/((df.srm$ratio2.b[df.sam$srm1] + df.srm$ratio2.b[df.sam$srm2])/2) 

这似乎工作,但我认为最后两行是有点乱。你知道如何改进代码吗?

相关问题