Как применить «для цикла» во всех столбцах в R? - PullRequest
0 голосов
/ 26 апреля 2018

У меня есть эти данные и для , которые я создал для преобразования всех элементов в столбце на основе условия (если). (Я знаю, что есть больше способов сделать это ...)

Вот оно:

S1 <- c(0,1,1,0,0,2,2,1,1,1,1,1,0)
S2 <- c(2,1,0,1,0,2,1,1,0,1,2,2,1)
S3 <- c(0,1,0,0,1,2,0,1,2,1,2,0,2)
S4 <- c(2,1,0,2,1,2,2,1,2,1,2,2,0)

df <- data.frame(S1,S2,S3,S4)

for (i in 1:nrow(df)){
  if(df[i,1] == 0){
    df[i,1] <- "A/A"
  }
  if(df[i,1] == 1){
    df[i,1] <- "A/T"
  }
  if(df[i,1] == 2){
    df[i,1] <- "T/T"
  }
  if(df[i,1] == "NaN"){
    df[i,1] <- 0
  }
}

Это актуально:

S1  S2  S3  S4
0   2   0   2
1   1   1   1
1   0   0   0

Когда я запускаю для , он работает только для первого столбца, поскольку я описал df[i,1]. Вопрос в том, как я могу сделать это для всех столбцов одновременно? Есть ли способ, которым я мог бы решить эту проблему?

Спасибо

Ответы [ 7 ]

0 голосов
/ 26 апреля 2018

Удивительно интересный вопрос, который поднимает много вопросов.

Что ж, если на самом деле все, что вы хотите сделать, это заменить значение в кадре данных другим значением, независимо от того, где оно появляется, вы можете просто использовать функцию [<- напрямую и избежать всех циклов и эквивалентных конструкций:

df[df==0] <- "A/A"
df[df==1] <- "A/T"
df[df==2] <- "T/A"
df[df=="NaN"] <- 0

Я бы предупредил, что здесь происходит огромное количество магии преобразования типов! После первого назначения все столбцы изменяются с числового на символьный. И все же все последующие сравнения все еще работают, потому что следующие все TRUE в R:

1 == "1"
"1" == 1

Это может быть опасный способ кодирования. Если вы действительно хотите знать, являются ли два объекта абсолютно одинаковыми, вы должны использовать следующее, что оценивается как FALSE:

identical(1, "1")

Также любопытно, что в вашем коде есть условие x == "NaN". Это хорошо для обнаружения строки "Nan", но если вы действительно хотите обнаружить значение IEEE 754 «не число», вам действительно нужно использовать функцию is.nan.

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

0 голосов
/ 28 апреля 2018

В ваших вопросах есть 2 вопроса:

  • "NaN" не может существовать в ваших данных, поскольку столбцы имеют тип numeric, я предполагаю, что вы имели в виду NaN.
  • 0 не может существовать в ваших выходных данных, поскольку столбцы будут иметь тип character, вместо этого я буду использовать NA, но вы можете использовать "0", если вы этого хотите.

Проблема, с которой вы столкнулись, заставляет меня думать, что вы, вероятно, должны использовать факторы, по крайней мере, это делает преобразование действительно простым:

df[] <- lapply(df,factor,c(0:2,NaN),c("A/A","A/T","T/T",NA))

#     S1  S2  S3  S4
# 1  A/A T/T A/A T/T
# 2  A/T A/T A/T A/T
# 3  A/T A/A A/A A/A
# 4  A/A A/T A/A T/T
# 5  A/A A/A A/T A/T
# 6  T/T T/T T/T T/T
# 7  T/T A/T A/A T/T
# 8  A/T A/T A/T A/T
# 9  A/T A/A T/T T/T
# 10 A/T A/T A/T A/T
# 11 A/T T/T T/T T/T
# 12 A/T T/T A/A T/T
# 13 A/A A/T T/T A/A

Если вы действительно хотите получить символы на выходе, а не факторы, вы можете использовать это:

df[] <- lapply(df,function(x)
  as.character(factor(x,c(0:2,NaN),c("A/A","A/T","T/T",NA))))
0 голосов
/ 26 апреля 2018

Рассмотрим также векторизованное вложенное ifelse в блоке столбцов (без применения / для циклов):

df[,1:4] <- ifelse(df[,1:4]== 0, "A/A", 
                   ifelse(df[,1:4]==1, "A/T", 
                          ifelse(df[,1:4]==2, "T/T", 
                                 ifelse(is.na(df[,1:4]), 0, NA))))
df

#     S1  S2  S3  S4
# 1  A/A T/T A/A T/T
# 2  A/T A/T A/T A/T
# 3  A/T A/A A/A A/A
# 4  A/A A/T A/A T/T
# 5  A/A A/A A/T A/T
# 6  T/T T/T T/T T/T
# 7  T/T A/T A/A T/T
# 8  A/T A/T A/T A/T
# 9  A/T A/A T/T T/T
# 10 A/T A/T A/T A/T
# 11 A/T T/T T/T T/T
# 12 A/T T/T A/A T/T
# 13 A/A A/T T/T A/A
0 голосов
/ 26 апреля 2018

Вы также можете использовать функцию mapvalues из пакета plyr с lapply или sapply

library(plyr)
df <- sapply(df, function(x){
  mapvalues(x,from  = c(0,1,2, "NaN"), to = c("A/A", "A/T", "T/T", 0))
})
0 голосов
/ 26 апреля 2018

В качестве альтернативы вы можете использовать mutate_all и case_when из пакета dplyr:

library(dplyr)
df %>% 
  mutate_all(funs(case_when(. == 0 ~ 'A/A',
                            . == 1 ~ 'A/T',
                            . == 2 ~ 'T/T',
                            . =="NaN" ~ '0')))
    S1  S2  S3  S4
1  A/A T/T A/A T/T
2  A/T A/T A/T A/T
3  A/T A/A A/A A/A
4  A/A A/T A/A T/T
5  A/A A/A A/T A/T
6  T/T T/T T/T T/T
7  T/T A/T A/A T/T
8  A/T A/T A/T A/T
9  A/T A/A T/T T/T
10 A/T A/T A/T A/T
11 A/T T/T T/T T/T
12 A/T T/T A/A T/T
13 A/A A/T T/T A/A
0 голосов
/ 26 апреля 2018

используйте sapply для перебора столбцов, а затем примените логическое сравнение с == для поиска и замены.

sapply(df, function(x){
  x[x==0] <- "A/A";
  x[x==1] <- "A/T";
  x[x==2] <- "T/T";
  x[x=="NaN"] <- 0;
  x
})

это производит:

      S1    S2    S3    S4   
 [1,] "A/A" "T/T" "A/A" "T/T"
 [2,] "A/T" "A/T" "A/T" "A/T"
 [3,] "A/T" "A/A" "A/A" "A/A"
 [4,] "A/A" "A/T" "A/A" "T/T"
 [5,] "A/A" "A/A" "A/T" "A/T"
 [6,] "T/T" "T/T" "T/T" "T/T"
 [7,] "T/T" "A/T" "A/A" "T/T"
 [8,] "A/T" "A/T" "A/T" "A/T"
 [9,] "A/T" "A/A" "T/T" "T/T"
[10,] "A/T" "A/T" "A/T" "A/T"
[11,] "A/T" "T/T" "T/T" "T/T"
[12,] "A/T" "T/T" "A/A" "T/T"
[13,] "A/A" "A/T" "T/T" "A/A"

Если вы хотите заменить df и сохранить структуру data.frame, тогда используйте lapply

df[,] <- lapply(df, function(x){
  x[x==0] <- "A/A";
  x[x==1] <- "A/T";
  x[x==2] <- "T/T";
  x[x=="NaN"] <- 0;
  x
})
0 голосов
/ 26 апреля 2018

Гнездо для цикла?

for (j in 1:4){
    for (i in 1:nrow(df)){
        if(df[i,j] == 0){
            df[i,j] <- "A/A"
        }
        if(df[i,j] == 1){
            df[i,j] <- "A/T"
        }
        if(df[i,j] == 2){
            df[i,j] <- "T/T"
        }
        if(df[i,j] == "NaN"){
            df[i,j] <- 0
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...