lapply внутри функции lapply

Только что узнав, что циклы плохие, я теперь пытаюсь использовать lapply внутри lapply. У меня есть серия последовательно пронумерованных кадров данных. В каждом я хотел бы заменить столбцы 5 и 8 буквами в зависимости от их значений, чтобы

`if the value is <2 the value is changed to "l" (for loss)`, 
`if it equals 2 the value should be "d"` 
and if >2 it should be "g".

Мой стартовый фрейм выглядит следующим образом

structure(list(Chromosome = structure(c(1L, 1L, 1L, 1L, 1L, 1L
), .Label = c("1", "10", "11", "12", "13", "14", "15", "16", 
"17", "18", "19", "2", "20", "21", "22", "3", "4", "5", "6", 
"7", "8", "9", "X", "Y"), class = "factor"), Start = c(1L, 100000001L, 
10000001L, 1000001L, 100500001L, 101000001L), Ratio.x = c(1.32971, 
0.990806, 0.991636, 1.01224, 1.00196, 1.00834), MedianRatio.x = c(1.32971, 
1.00378, 0.988738, 0.979015, 1.00378, 1.00378), CopyNumber.x = c(3L, 
2L, 2L, 1L, 2L, 1L), Ratio.y = c(-1, 0.718527, 1.09204, -1, 1.07779, 
1.41024), MedianRatio.y = c(-1, 1.07779, 0.814437, 0.814437, 
1.07779, 1.07779), CopyNumber.y = c(2L, 2L, 2L, 2L, 2L, 2L)), .Names = c("Chromosome", 
"Start", "Ratio.x", "MedianRatio.x", "CopyNumber.x", "Ratio.y", 
"MedianRatio.y", "CopyNumber.y"), row.names = c(NA, 6L), class = "data.frame")

Код, который я использую, выглядит следующим образом

lst <- mget(ls(pattern='total\\d+'))

lapply(lst, function(df) {
  lapply(df, function(x){
  #Mark out diploid as "d"
  x[,5][x[,5] == "2"] <- "d"
  x[,8][x[,8] == "2"] <- "d"
  #Deletions are "l"
  x[,5][x[,5] < 2 & x[,5] !="d"] <- "l"
  x[,8][x[,8] < 2 & x[,8] !="d"] <- "l"
  #Gains are "g"
  x[,5][x[,5] > 2 & x[,5] !="l" & x[,5] !="d"] <- "g"
  x[,8][x[,8] > 2 & x[,8] !="l" & x[,8] !="d"] <- "g"
  #Compare the g's l's and d's
}
)})

однако я продолжаю получать ошибку

Error in `[.default`(`*tmp*`, , 5) : incorrect number of dimensions

2 ответа

Вот альтернатива, которая полностью исключает циклы (скрытые или иные):

df;
##   Chromosome     Start  Ratio.x MedianRatio.x CopyNumber.x   Ratio.y MedianRatio.y CopyNumber.y
## 1          1         1 1.329710      1.329710            3 -1.000000     -1.000000            2
## 2          1 100000001 0.990806      1.003780            2  0.718527      1.077790            2
## 3          1  10000001 0.991636      0.988738            2  1.092040      0.814437            2
## 4          1   1000001 1.012240      0.979015            1 -1.000000      0.814437            2
## 5          1 100500001 1.001960      1.003780            2  1.077790      1.077790            2
## 6          1 101000001 1.008340      1.003780            1  1.410240      1.077790            2
df[,c(5,8)] <- c('l','d','g')[sign(as.matrix(df[,c(5,8)])-2)+2];
df;
##   Chromosome     Start  Ratio.x MedianRatio.x CopyNumber.x   Ratio.y MedianRatio.y CopyNumber.y
## 1          1         1 1.329710      1.329710            g -1.000000     -1.000000            d
## 2          1 100000001 0.990806      1.003780            d  0.718527      1.077790            d
## 3          1  10000001 0.991636      0.988738            d  1.092040      0.814437            d
## 4          1   1000001 1.012240      0.979015            l -1.000000      0.814437            d
## 5          1 100500001 1.001960      1.003780            d  1.077790      1.077790            d
## 6          1 101000001 1.008340      1.003780            l  1.410240      1.077790            d

Внутренний lapply на самом деле не имеет смысла - вы бы и здесь не использовали цикл.

Вместо этого вы можете заменить столбец следующим образом:

classify_cnv = function (column)
    ifelse(column < 2, 'l', ifelse(column > 2, 'g', 'd'))

... и примените это к двум колонкам:

df$CopyNumber.x = classify_cnv(df$CopyNumber.x)
df$CopyNumber.y = classify_cnv(df$CopyNumber.y)

Затем вы можете положить это внутри lapply через data.frames:

classify_all_cnvs = function (df) {
    df$CopyNumber.x = classify_cnv(df$CopyNumber.x)
    df$CopyNumber.y = classify_cnv(df$CopyNumber.y)
    df
}

result = lapply(lst, classify_all_cnvs)

Тем не менее, это может быть более целесообразным заменить список data.frameс одной большой data.frameс дополнительным столбцом, указывающим, из какой исходной таблицы поступают данные. Как это сделать лучше всего зависит от вашей точной структуры данных.

Другие вопросы по тегам