在 R 中执行 lapply 时忽略特定级别
Ignore specific levels when performing lapply in R
我在 R 中有一个数据框(40000 个变量的 500 个观测值),其中所有列都由一个或两个字母组成,中间穿插着“1”和“3”。例如,mydata[45:50,20:25]
45 C A 3 T C C
46 C G T C C A
47 C A G T C C
48 1 A T 3 C 3
49 C A G T C C
50 T A T C C A
我只想替换字母而不是数字。我的目标是根据字母的频率将字母替换为“0”或“2”。因此,出现频率最高的字母变为“0”,出现频率最低的字母变为“2”。如果只有一个字母,那将变成'0'。
我可以在不忽略散布的“1”和“3”的情况下使用:
data.frame(lapply(mydata[45:50,20:25], function(x){as.numeric(factor(x, levels = names(sort(-table(x)))))}))
产生:
1 1 1 3 1 1 1
2 1 2 1 2 1 2
3 1 1 2 1 1 1
4 2 1 1 3 1 3
5 1 1 2 1 1 1
6 3 1 1 2 1 2
但是,我希望能够在忽略原始数据框中的“1”和“3”的情况下做到这一点。
感谢任何帮助。谢谢。
我会在这里使用 matrix
。
使用 grep
我们制作了 table
的频率,我们 rank
在它们的负值上减去一得到零。因为我不确定你想要什么,所以我选择 "first"
来获得一个整数(选项见 ?rank
)。
然后我们match
频率上的字母。最后,我们使用 type.convert
转换回数据框以获得数字格式。
m <- as.matrix(d)
ftb <- table(grep("[\p{Lu}]", m, perl=TRUE, value=TRUE))
ftb <- rank(-ftb, ties.method="first") - 1
m.res <- apply(m, 1:2, function(x) ifelse(x %in% names(ftb), ftb[match(x, names(ftb))], x))
d.res <- type.convert(as.data.frame(m.res))
d.res
# V1 V2 V3 V4 V5 V6 V7
# 1 45 0 1 3 2 0 0
# 2 46 0 3 2 0 0 1
# 3 47 0 1 3 2 0 0
# 4 48 1 1 2 3 0 3
# 5 49 0 1 3 2 0 0
# 6 50 2 1 2 0 0 1
编辑
既然你想查看列频率,我们可以使用 lapply
中的方法(没有矩阵转换)。然后我们可以将排名乘以因子 2。
f <- 2
d[-1] <- lapply(d[-1], function(x) {
ftb <- (rank(-table(grep("[\p{Lu}]", x, perl=TRUE, value=TRUE)),
ties.method="first") - 1)*f
stopifnot(length(ftb) <= 2)
x <- ifelse(x %in% names(ftb), ftb[match(x, names(ftb))], x)
as.numeric(x)
})
d
# V1 V2 V3 V4 V5 V6 V7
# 1 45 0 0 3 0 0 0
# 2 46 0 2 0 2 0 2
# 3 47 0 0 2 0 0 0
# 4 48 1 0 0 3 0 3
# 5 49 0 0 2 0 0 0
# 6 50 2 0 0 2 0 2
数据:
d <- structure(list(V1 = 45:50, V2 = c("C", "C", "C", "1", "C", "T"
), V3 = c("A", "G", "A", "A", "A", "A"), V4 = c("3", "T", "G",
"T", "G", "T"), V5 = c("T", "C", "T", "3", "T", "C"), V6 = c("C",
"C", "C", "C", "C", "C"), V7 = c("C", "A", "C", "3", "C", "A"
)), class = "data.frame", row.names = c(NA, -6L))
我在 R 中有一个数据框(40000 个变量的 500 个观测值),其中所有列都由一个或两个字母组成,中间穿插着“1”和“3”。例如,mydata[45:50,20:25]
45 C A 3 T C C
46 C G T C C A
47 C A G T C C
48 1 A T 3 C 3
49 C A G T C C
50 T A T C C A
我只想替换字母而不是数字。我的目标是根据字母的频率将字母替换为“0”或“2”。因此,出现频率最高的字母变为“0”,出现频率最低的字母变为“2”。如果只有一个字母,那将变成'0'。
我可以在不忽略散布的“1”和“3”的情况下使用:
data.frame(lapply(mydata[45:50,20:25], function(x){as.numeric(factor(x, levels = names(sort(-table(x)))))}))
产生:
1 1 1 3 1 1 1
2 1 2 1 2 1 2
3 1 1 2 1 1 1
4 2 1 1 3 1 3
5 1 1 2 1 1 1
6 3 1 1 2 1 2
但是,我希望能够在忽略原始数据框中的“1”和“3”的情况下做到这一点。
感谢任何帮助。谢谢。
我会在这里使用 matrix
。
使用 grep
我们制作了 table
的频率,我们 rank
在它们的负值上减去一得到零。因为我不确定你想要什么,所以我选择 "first"
来获得一个整数(选项见 ?rank
)。
然后我们match
频率上的字母。最后,我们使用 type.convert
转换回数据框以获得数字格式。
m <- as.matrix(d)
ftb <- table(grep("[\p{Lu}]", m, perl=TRUE, value=TRUE))
ftb <- rank(-ftb, ties.method="first") - 1
m.res <- apply(m, 1:2, function(x) ifelse(x %in% names(ftb), ftb[match(x, names(ftb))], x))
d.res <- type.convert(as.data.frame(m.res))
d.res
# V1 V2 V3 V4 V5 V6 V7
# 1 45 0 1 3 2 0 0
# 2 46 0 3 2 0 0 1
# 3 47 0 1 3 2 0 0
# 4 48 1 1 2 3 0 3
# 5 49 0 1 3 2 0 0
# 6 50 2 1 2 0 0 1
编辑
既然你想查看列频率,我们可以使用 lapply
中的方法(没有矩阵转换)。然后我们可以将排名乘以因子 2。
f <- 2
d[-1] <- lapply(d[-1], function(x) {
ftb <- (rank(-table(grep("[\p{Lu}]", x, perl=TRUE, value=TRUE)),
ties.method="first") - 1)*f
stopifnot(length(ftb) <= 2)
x <- ifelse(x %in% names(ftb), ftb[match(x, names(ftb))], x)
as.numeric(x)
})
d
# V1 V2 V3 V4 V5 V6 V7
# 1 45 0 0 3 0 0 0
# 2 46 0 2 0 2 0 2
# 3 47 0 0 2 0 0 0
# 4 48 1 0 0 3 0 3
# 5 49 0 0 2 0 0 0
# 6 50 2 0 0 2 0 2
数据:
d <- structure(list(V1 = 45:50, V2 = c("C", "C", "C", "1", "C", "T"
), V3 = c("A", "G", "A", "A", "A", "A"), V4 = c("3", "T", "G",
"T", "G", "T"), V5 = c("T", "C", "T", "3", "T", "C"), V6 = c("C",
"C", "C", "C", "C", "C"), V7 = c("C", "A", "C", "3", "C", "A"
)), class = "data.frame", row.names = c(NA, -6L))