Как заменить нули на половину минимального значения в столбце? - PullRequest
1 голос
/ 28 января 2020

Я пытаюсь заменить 0 в моем фрейме данных тысячами строк и столбцов с половиной минимального значения больше нуля из этого столбца. Я также не хотел бы включать первые четыре столбца, поскольку они являются индексами.

Так что, если я начну с чего-то вроде этого:

index <- c("100p", "200p", 300p" 400p")
ratio <- c(5, 4, 3, 2)
gene <- c("gapdh", NA, NA,"actb"
species <- c("mouse", NA, NA, "rat")
a1 <- c(0,3,5,2)
b1 <- c(0, 0, 4, 6)
c1 <- c(1, 2, 3, 4)

as.data.frame(q) <- cbind(index, ratio, gene, species, a1, b1, c1)

index ratio gene  species a1 b1 c1
100p    5   gapdh mouse   0  0  1
200p    4    NA    NA     3  0  2
300p    3    NA    NA     5  4  3
400p    2   actb  rat     2  6  4

Я бы надеялся получить такой результат, как этот :

index ratio gene  species a1 b1 c1
100p    5   gapdh mouse   1  2  1
200p    4    NA    NA     3  2  2
300p    3    NA    NA     5  4  3
400p    2   actb  rat     2  6  4

Я пробовал следующий код: apply(q[-4], 2, function(x) "[<-"(x, x==0, min(x[x > 0]) / 2))

, но постоянно получаю сообщение об ошибке: Error in min(x[x > 0])/2 : non-numeric argument to binary operator

Любая помощь по этому вопросу? Большое спасибо!

Ответы [ 3 ]

2 голосов
/ 28 января 2020

Мы можем использовать lapply и replace 0 значений с минимальным значением в столбце на 2.

cols<- 5:7
q[cols] <- lapply(q[cols], function(x) replace(x, x == 0, min(x[x>0], na.rm = TRUE)/2))

q
#  index ratio  gene species a1 b1 c1
#1  100p     5 gapdh   mouse  1  2  1
#2  200p     4  <NA>    <NA>  3  2  2
#3  300p     3  <NA>    <NA>  5  4  3
#4  400p     2  actb     rat  2  6  4

В dplyr мы можем использовать mutate_at

library(dplyr)
q %>%  mutate_at(cols,~replace(., . == 0, min(.[.>0], na.rm = TRUE)/2))

данные

q <- structure(list(index = structure(1:4, .Label = c("100p", "200p", 
"300p", "400p"), class = "factor"), ratio = c(5, 4, 3, 2), gene = structure(c(2L, 
NA, NA, 1L), .Label = c("actb", "gapdh"), class = "factor"), 
species = structure(c(1L, NA, NA, 2L), .Label = c("mouse", 
"rat"), class = "factor"), a1 = c(0, 3, 5, 2), b1 = c(0, 
0, 4, 6), c1 = c(1, 2, 3, 4)), class = "data.frame", row.names = c(NA, -4L))
1 голос
/ 28 января 2020

Немного другой (и потенциально более быстрый для больших наборов данных) вариант dplyr с небольшим количеством математики может быть:

q %>%
 mutate_at(vars(5:length(.)), ~ (. == 0) * min(.[. != 0])/2 + .)

  index ratio  gene species a1 b1 c1
1  100p     5 gapdh   mouse  1  2  1
2  200p     4  <NA>    <NA>  3  2  2
3  300p     3  <NA>    <NA>  5  4  3
4  400p     2  actb     rat  2  6  4

И то же самое с base R:

q[, 5:length(q)] <- lapply(q[, 5:length(q)], function(x) (x == 0) * min(x[x != 0])/2 + x)
0 голосов
/ 28 января 2020

Для справки, учитывая ваш оригинальный код, я считаю, что ваша функция не была проблемой. Вместо этого ошибка возникает из-за применения функции к нечисловым c данным.

# original data
index <- c("100p", "200p", "300p" , "400p")
ratio <- c(5, 4, 3, 2)
gene <- c("gapdh", NA, NA,"actb")
species <- c("mouse", NA, NA, "rat")
a1 <- c(0,3,5,2)
b1 <- c(0, 0, 4, 6)
c1 <- c(1, 2, 3, 4)

# data frame
q <- as.data.frame(cbind(index, ratio, gene, species, a1, b1, c1))

# examine structure (all cols are factors) 
str(q)

# convert factors to numeric  
fac_to_num <- function(x){
  x <- as.numeric(as.character(x))
  x
}

# apply to cols 5 thru 7 only
q[, 5:7] <- apply(q[, 5:7],2,fac_to_num)

# examine structure  
str(q)

# use original function only on numeric data 
apply(q[, 5:7], 2, function(x) "[<-"(x, x==0, min(x[x > 0]) / 2))
...