2013-09-07 15 views
8

cercavo la funzione numerica piuttosto essenziale digit sum in R.Digit funzione di somma in R

  • non ho trovato una funzione preinstallata.
  • Anche nella libreria R estesa di Stackoverflow non ho trovato alcun record.

quindi cercato me stesso termina con seguente funzione:

# Function to calculate a digit sum 
digitsum = function (x) {sum(as.numeric(unlist(strsplit(as.character(x), split="")))) } 

mi funziona, ma ho ancora lottare con i seguenti due domande:

  1. C'è veramente in pianura R alcuna funzione per somma cifre ?
  2. Esiste un modo più intelligente per codificare questa funzione?
+3

Come ha detto DWin, non c'è quasi nessuna funzione per questa funzione se non negli angoli polverosi della teoria dei numeri. Non troverai neanche una funzione di prodotto a cifre. –

risposta

12

Questo dovrebbe essere meglio:

digitsum <- function(x) sum(floor(x/10^(0:(nchar(x) - 1))) %% 10) 
+0

Grazie, anche io non capisco davvero come funziona - funziona bene dopo pochi test. – user2030503

+0

@ user2030503, questo tipico algoritmo verrebbe scritto usando 'while' in altri linguaggi di programmazione, mentre qui possiamo sfruttare la vettorizzazione. Ottengo ogni cifra separatamente dividendo un po 'di potenza di 10 e ottenendo un resto. Guarda 'x/10^(0: (nchar (x) - 1))', quindi aggiungi 'floor',' %% 10' per capirlo meglio. – Julius

+1

+1 wow. Questo è super intelligente. Adoro il modo in cui funziona. –

4

Non sono sicuro del motivo per cui si penserebbe che ci sarebbe una funzione integrata per farlo. Non è davvero un'operazione statistica. Più di una sorta di procedura di teoria dei numeri. (Ci sono molti esempi che possono essere trovati con una ricerca degli archivi di Rhelp. Io uso Markmail per quello scopo ma ci sono altri motori di ricerca come RSeek, GMane e la pagina Web di Newcastle. La tua funzione richiederebbe una serie di numeri e restituirà un numero unico che era la somma cifre di tutti loro se questo fosse l'obiettivo allora sembra ragionevolmente progettato avrei immaginato che uno vorrebbe le somme cifra di ogni numero:..

sapply(c(1,2,123), 
     function(x) sum(as.numeric(unlist(strsplit(as.character(x), split=""))))) 
[1] 1 2 6 

C'è una "digitalizzazione "funciton digitsBase in pkg: GLDEX, e si potrebbe sostituire l'as.numeric (non elencati (split (as.character (x)," "))) con quella funzione:

digitsBase(x, 10) 
+0

Grazie, il tuo suggerimento per Markmail è molto utile. Non ne ero a conoscenza. – user2030503

+1

Ero un po 'seccato che quando ho tentato di collegarmi direttamente a Rhelp, ho ricevuto un messaggio che diceva che i collegamenti a r-help dot r-project dot org non erano consentiti. –

5

mi chiedevo quale dei tre metodi suggeriti (più un quarto) è il più veloce così ho fatto qualche analisi comparativa.

  1. digitsum1 <- function(x) sum(as.numeric(unlist(strsplit(as.character(x), split = ""))))

  2. digitsum2 <- function(x) sum(floor(x/10^(0:(nchar(x) - 1))) %% 10)

  3. Utilizzando la funzione digitsBase dal pacchetto GLDEX:

    library(GLDEX, quietly = TRUE) 
    digitsum3 <- function(x) sum(digitsBase(x, base = 10)) 
    
  4. Sulla base di una funzione di Greg Neve nel R-help mailing list:

    digitsum4 <- function(x) sum(x %/% 10^seq(0, length.out = nchar(x)) %% 10)

codice riferimento:

library(microbenchmark, quietly = TRUE) 
# define check function 
my_check <- function(values) { 
    all(sapply(values[-1], function(x) identical(values[[1]], x))) 
} 
x <- 1001L:2000L 
microbenchmark(
    sapply(x, digitsum1), 
    sapply(x, digitsum2), 
    sapply(x, digitsum3), 
    sapply(x, digitsum4), 
    times = 100L, check = my_check 
) 

benchmark risultati:

#> Unit: milliseconds 
#>     expr min lq mean median uq max neval 
#> sapply(x, digitsum1) 3.41 3.59 3.86 3.68 3.89 5.49 100 
#> sapply(x, digitsum2) 3.00 3.19 3.41 3.25 3.34 4.83 100 
#> sapply(x, digitsum3) 15.07 15.85 16.59 16.22 17.09 24.89 100 
#> sapply(x, digitsum4) 9.76 10.29 11.18 10.56 11.48 45.20 100 

variante 2 è leggermente più veloce variante 1 mentre varianti 4 e 3 sono molto più lento. Anche se il codice della variante 4 sembra essere simile alla variante 2, la variante 4 è meno efficiente (ma comunque migliore della variante 3).

I risultati completi del benchmark (compresi i grafici) sono github.