我有这个数据和 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]
。问题是,我如何同时为所有列执行此操作?
有没有办法解决这个问题?
由于
答案 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_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
答案 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
函数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))
})
答案 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
函数的值。
如果您确实想知道如何将任何类型的函数应用于数据框的所有列,请参阅问题的其他答案。