najczęstsza wartość jest konwertowana na 1, druga najczęściej używana wartość to 2 itd.
Można użyć table
, sort
, factor
:
convert <- function(x) as.integer(factor(x, levels = names(sort(-table(x)))))
num1 <- convert(df1$snp1)
num2 <- convert(df$2snp2)
zastosować to do wszystkich kolumn w poręczny sposób?
Zastosowanie lapply
:
df2 <- as.data.frame(lapply(df1, FUN = convert))
Dyskusja:
@thelatemail wspomniano możliwość zastosowania match()
. Jego użycie levels()
zakłada, że wszystkie kolumny df1
są łatwo czynnikami. Często jest to prawdą, chyba że niektórzy, jak ja, ustawili options(stringsAsFactors = FALSE)
w pliku startowym R. Zamieniłbym levels()
na names()
, więc jego pomysł będzie działał zarówno dla wejścia łańcuchowego, jak i wejściowego.
convert2 <- function(x) {
tab <- table(x)
match(x, names(tab)[order(-tab)])
}
Nasze pierwsze pytanie brzmi, jest znacznie szybszy niż convert2()
convert()
?
Definiujemy funkcję zabawka dla pomiaru wydajności pomiędzy dwoma funkcjami:
timing <- function(n, rep, FACTOR = FALSE, FUN1, FUN2) {
## sample data
x <- c("AA", "AT", "TT")[sample(1:3, n, replace = TRUE)]
if (FACTOR) x <- factor(x)
## method 1: as.integer(factor())
t1 <- system.time(for (k in 1:rep) {tmp <- FUN1(x); tmp <- FUN1(x); tmp <- FUN1(x); tmp <- FUN1(x)})
## method 2: match()
t2 <- system.time(for (k in 1:rep) {tmp <- FUN2(x); tmp <- FUN2(x); tmp <- FUN2(x); tmp <- FUN2(x)})
## timing summary
cat("FUN1\n"); print(t1)
cat("FUN2\n"); print(t2)
}
Dla wejścia ciąg znaków mamy:
> timing(n = 20000, rep = 1000, FACTOR = FALSE, FUN1 = convert, FUN2 = convert2)
FUN1 ## convert(), using as.integer(factor())
user system elapsed
18.772 0.212 19.052
FUN2 ## convert2(), using match()
user system elapsed
17.792 0.100 17.920
Dla wejścia czynnika, mamy:
> timing(n = 20000, rep = 1000, FACTOR = TRUE, FUN1 = convert, FUN2 = convert2)
FUN1 ## convert(), using as.integer(factor())
user system elapsed
17.180 0.144 17.384
FUN2 ## convert2(), using match()
user system elapsed
15.500 0.168 15.693
A więc:
- gdy dane wejściowe są czynnikami, obie metody są marginalnie szybsze;
convert2()
jest o 5% - 10% szybsza niż convert1()
.
Teraz ograniczmy to, że mamy czynnik wejściowy, możemy sprawić, że convert2()
będzie szybszy. Rozważ:
## only works for factor input!!
convert3 <- function(x) {
tab <- table(x)
match(as.integer(x), (seq_along(tab))[order(-tab)])
}
Tutaj użyliśmy dopasowania liczb całkowitych.Porównaj convert2()
i convert3()
:
> timing(n = 20000, rep = 1000, FACTOR = TRUE, FUN1 = convert2, FUN2 = convert3)
FUN1 ## convert2(), using string match
user system elapsed
15.168 0.156 15.351
FUN2 ## convert3(), using integer match
user system elapsed
14.032 0.116 14.174
'data.frame (lapply (DF1, function (x) {as.numeric (współczynnik (x, poziom = Nazwy (porządek (-table (x)))))})) ' – alistaire