我有一个巨大的1000 x 100000数据帧,如下所示重新编码为数字值。
myd <- data.frame (v1 = sample (c("AA", "AB", "BB", NA), 10, replace = T),
v2 = sample (c("CC", "CG", "GG", NA), 10, replace = T),
v3 = sample (c("AA", "AT", "TT", NA) , 10, replace = T),
v4 = sample (c("AA", "AT", "TT", NA) , 10, replace = T),
v5 = sample (c("CC", "CA", "AA", NA) , 10, replace = T)
)
myd
v1 v2 v3 v4 v5
1 AB CC <NA> <NA> AA
2 AB CG TT TT AA
3 AA GG AT AT CA
4 <NA> <NA> <NA> AT <NA>
5 AA <NA> AA <NA> CA
6 BB <NA> TT TT CC
7 AA GG AA AT CA
8 <NA> GG <NA> AT CA
9 AA <NA> AT <NA> CC
10 AA GG TT AA CC
每个变量都有四个唯一值。
unique(myd$v1)
[1] AB AA <NA> BB
Levels: AA AB BB
unique(myd$v2)
[1] CC CG GG <NA>
Levels: CC CG GG
此类唯一值可以是任意组合,但由两个字母组成( - 不包括NA)。例如&#34; A&#34;,&#34; B&#34;在第一种情况下,将组合&#34; AA&#34;,&#34; AB&#34;,&#34; BB&#34;。这些的数字代码分别为1,0,-1。类似地,对于第二种情况字母表&#34; C&#34;,&#34; G&#34;制作&#34; CC&#34;,&#34; CG&#34;,&#34; GG&#34;,因此数字代码分别为1,0,-1。因此,上述myd需要重新编码为:
myd
v1 v2 v3 v4 v5
1 0 1 <NA> <NA> 1
2 0 0 -1 -1 1
3 1 -1 0 0 0
4 <NA> <NA> <NA> 0 <NA>
5 1 <NA> 1 < NA> 0
6 -1 <NA> -1 -1 -1
7 1 -1 1 0 0
8 <NA> -1 <NA> 0 0
9 1 <NA> 0 <NA> -1
10 1 -1 -1 1 -1
答案 0 :(得分:8)
我将发布一个不同的解决方案 - (跳至data.table
获取超快速方法!)
如果您想重新编码AA, AB, BB
,1,0,-1
等,您可以使用索引(以及数字解决方案的因素)。如果您愿意,这将允许您进行不同的重新编码!
simple_recode <- function(.x, new_codes){
new_codes[as.numeric(.x)]
}
as.data.frame(lapply( myd, simple_recode, new_codes = 1:-1))
factor
您可以通过调用factor
并将新关卡调整为labels
as.data.frame(lapply(myd, factor, labels = 1:-1))
效率data.table
如果您的数据很大,那么我建议使用data.table
方法来节省内存和时间。
library(data.table)
DT <- as.data.table(myd)
as.data.table(DT[,lapply(.SD, simple_recode, new_codes = 1:-1))])
或者,更有效率
as.data.table(DT[, lapply(.SD, setattr, 'levels', 1:-1)])
或者,更有效率(修改现有级别,避免as.data.table调用)
for(name in names(DT)){
setattr(DT[[name]],'levels',1:-1)
}
setattr
通过引用修改,因此不会复制。
正如此大数据集
所示# some big data (100 columns, 1e6 rows)
big <- replicate(100, factor(sample(c('AA','AB','BB', NA), 1e6, T)), simplify = F)
bigDT <- as.data.table(big)
system.time({
for(name in names(big)){
setattr(big[[name]],'levels',1:-1)
}
}))
## user system elapsed
## 0 0 0
答案 1 :(得分:7)
您可以利用这样一个事实,即您的数据是因素,其下方有数字索引。
例如:
> as.numeric(myd$v1)
[1] 2 2 1 NA 1 3 1 NA 1 1
数值对应于因子的levels()
:
> levels(myd$v1)
[1] "AA" "AB" "BB"
所以1 == AA
,2 == AB
,3 == BB
......依此类推。
因此,您只需将数据转换为数字,然后应用必要的数学运算即可按比例缩放数据。所以我们可以减去2,然后乘以-1得到你的结果:
(sapply(myd, as.numeric) - 2) * -1
#-----
v1 v2 v3 v4 v5
[1,] 0 1 NA NA 1
[2,] 0 0 -1 -1 1
[3,] 1 -1 0 0 0
[4,] NA NA NA 0 NA
[5,] 1 NA 1 NA 0
[6,] -1 NA -1 -1 -1
[7,] 1 -1 1 0 0
[8,] NA -1 NA 0 0
[9,] 1 NA 0 NA -1
[10,] 1 -1 -1 1 -1
答案 2 :(得分:4)
如果您设置了一个赋值,以便LHS具有适当的结构,您可以使用因子的隐式强制值作为所需值的索引:
> myd[] <- c(-1,0,1)[data.matrix(myd)]
> myd
v1 v2 v3 v4 v5
1 NA 0 0 0 1
2 -1 1 0 0 -1
3 0 NA 1 0 0
4 NA -1 -1 0 -1
5 -1 0 1 -1 NA
6 0 NA 0 1 NA
7 NA 0 1 NA -1
8 0 0 0 -1 1
9 -1 NA 1 -1 NA
10 0 1 1 NA NA