我已经找到了如何以一种简单的方式改变因子的水平。我的问题是我有三个列(因子),它们有一些共同的水平。我需要确定我可以改变 - 一般来说,因为明年这个因素的水平将有不同的名称 - 相同的“新”水平的因素水平相等。例:
> data<-read.table(head=T,"F2_SULMaturação_Conjunta.txt")
> data[25:35,1:5]
OBS POP IDPOP IDMOM IDDAD
25 25 MUR3 MUR3 BMXPotênciaRR M9056RR
26 26 MUR9 MUR9 BMXPotênciaRR M8221RR
27 27 MUR18 MUR18 BMXPotênciaRR P98N71
28 28 MUR29 MUR29 BMXPotênciaRR CONQUISTA
29 29 GENIT BMXPotênciaRR 0 0
30 30 GENIT NA5909RR 0 0
31 31 MUR25 MUR25 DM5958IPRO CONQUISTA
32 32 MUR27 MUR27 TMG7062IPRO CONQUISTA
33 33 GENIT DM5958IPRO 0 0
34 34 GENIT P98N71 0 0
35 35 MUR1 MUR1 BMXApoloRR M9056RR
> levels(data$IDDAD)
[1] "0" "CONQUISTA" "M8221RR" "M9056RR" "P98N71"
> levels(data$IDMOM)
[1] "0" "BMXApoloRR" "BMXPotênciaRR" "DM5958IPRO"
"DM6563IPRO"
[6] "NA5909RR" "TMG7062IPRO"
> levels(data$IDPOP)
[1] "BMXApoloRR" "BMXPotênciaRR" "CONQUISTA" "DM5958IPRO"
"DM6563IPRO"
[6] "M8221RR" "M9056RR" "MUR1" "MUR13" "MUR14"
[11] "MUR15" "MUR16" "MUR17" "MUR18" "MUR2"
[16] "MUR24" "MUR25" "MUR26" "MUR27" "MUR28"
[21] "MUR29" "MUR3" "MUR7" "MUR8" "MUR9"
[26] "NA5909RR" "P98N71" "TMG7062IPRO"
请注意,某些级别的“IDPOP”,“IDMOM”和“IDDAD”是相同的,即:“BMXPotênciaRR”。我正在寻找一个代码,也许这允许我在同一行中设置两个具有相应“新级别”的向量,并批量进行此更改。例:
> a<-c("BMXPotênciaRR","DM5958IPRO", "TMG7062IPRO")
> b<-c("1","2","3")
> a
[1] "BMXPotênciaRR" "DM5958IPRO" "TMG7062IPRO"
> b
[1] "1" "2" "3"
由于我必须以一般方式编写代码,因此我不打算编写级别,而是通过“级别(...)”捕获它们。
如果我们需要在多列中更改常见的levels
,请使用levels
识别常见的intersect
# columns of interest
nm1 <- c("IDDAD", "IDMOM", "IDPOP")
v1 <- Reduce(intersect, lapply(data[nm1], levels))
vector
的levels
的新水平(可以定制levels
)
v2 <- seq_along(v1)
将新的levels
分配给列
data[nm1] <- lapply(data[nm1], function(x) {
levels(x)[levels(x) %in% v1] <- v2
x
})
假设问题是如何将数据框中所有或指定因子列的级别设置为其级别的并集。
假设我们有几个因子和非因子列的DF
(在最后的注释中显示)。
1)Base R首先计算is.fac
是一个逻辑向量,用于识别哪些列是因子。 (如果你想设置一些因子列然后手动设置is.fac
- is.fac可以是一个逻辑向量,每列有一个元素,或者它可以是要处理的列索引的整数向量,也可以是是一个感兴趣的列名称的字符向量。例如,如果我们只想考虑前两列,我们可以设置is.fac <- 1:2
或is.fac <- c("A", "B")
。)
然后使用Reduce
来获得他们关卡的联盟,levs
。如果级别的顺序很重要,那么请对levs
进行排序。
最后将每个因子的水平设置为levs
。
is.fac <- sapply(DF, is.factor)
levs <- Reduce(union, lapply(DF[is.fac], levels), init = NULL)
fix_levs <- function(x, levs) factor(as.character(x), levels = levs)
DF2 <- replace(DF, is.fac, lapply(DF[is.fac], fix_levs, levs))
我们可以看到因子列的级别是相同的。例如,请注意,“q”在DF
中出现为DF$A
中的第3级,DF$B
中的第2级和DF$C
中的第一级,但“c”始终显示为DF2
中所有三列中的第三级。
DF$A
## [1] a b c
## Levels: a b c
DF$B
## [1] b c d
## Levels: b c d
DF$C
## [1] c d e
## Levels: c d e
DF2$A
## [1] a b c
## Levels: a b c d e
DF2$B
## [1] b c d
## Levels: a b c d e
DF2$C
## [1] c d e
## Levels: a b c d e
2)字符另一种可能性是只使用字符列。然后我们不必担心水平是否相同。使用上面的is.fac
:
DF3 <- replace(DF, is.fac, lapply(DF[is.fac], as.character))
3)forcats forcats包为此目的有fct_unify
。使用上面的is.fac
:
library(forcats)
DF4 <- replace(DF, is.fac, fct_unify(DF[is.fac]))
我们使用了以下测试数据框:
DF <- data.frame(A = letters[1:3], B = letters[2:4], C = letters[3:5], D = 1:3)