如何在R的所有列中应用“for循环”?

时间:2018-04-26 15:22:52

标签: r for-loop if-statement multiple-columns

我有这个数据和 for 我创建的基于条件(if)转换列中的所有元素。 (我知道有更多方法可以做到这一点......)

这是:

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

当我运行 for 时,它仅适用于第一列,因为我描述了df[i,1]。问题是,我如何同时为所有列执行此操作? 有没有办法解决这个问题?

由于

7 个答案:

答案 0 :(得分:4)

使用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
})

答案 1 :(得分:3)

或者,您可以使用包mutate_all中的case_whendplyr

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

答案 2 :(得分:1)

在整个列块中考虑矢量化嵌套ifelse(无应用/ for循环):

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

答案 3 :(得分:1)

您的问题有两个问题:

  • "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))))

答案 4 :(得分:0)

嵌套for循环?

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
        }
    }
}

答案 5 :(得分:0)

您还可以使用plyr包中的mapvalues函数lapplysapply

library(plyr)
df <- sapply(df, function(x){
  mapvalues(x,from  = c(0,1,2, "NaN"), to = c("A/A", "A/T", "T/T", 0))
})

答案 6 :(得分:0)

引发许多问题的令人惊讶的有趣问题。

好吧,如果真的想要做的就是用一些其他值替换数据框中的值,无论它出现在何处,您都可以直接使用[<-函数并避免所有循环和等效结构:

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

我会提醒说,这里有大量的类型转换魔法!在第一次分配后,所有列都从数字更改为字符。然而,所有后续比较仍然有效,因为以下是R中的所有TRUE

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

这可能是一种危险的代码方式。如果您真的想知道两个对象是否完全相同,您可以使用以下内容,其结果为FALSE

identical(1, "1")

您也很好奇您的代码中包含条件x == "NaN"。这对于检测字符串 "Nan"很好,但如果您确实想要检测IEEE 754&#34;而不是数字&#34;您实际上必须使用is.nan函数的值。

如果您确实想知道如何将任何类型的函数应用于数据框的所有列,请参阅问题的其他答案。