2013-01-18 10 views
17

sto Gestione di un DB con formato di ora come:Pad con zeri a larghezza comune

HOUR ID 
1 2 
10 4 
5 6 
20 6 

vorrei inserire uno zero nel valore con 1 personaggio e memorizzarli in una nuova colonna denominata Nhour, come:

NHOUR HOUR ID 
01 1 2 
10 10 4 
05 5 6 
20 20 6 

Fino ad ora sto lottando con qualcosa di simile (seguo alcuni suggerimenti già previsti IfElse nel forum):

DB$NHOUR<-with(DB,ifelse(nchar(HOUR,type="chars")==1),sprintf("%02d",HOUR),as.numeric(HOUR)) 

ma senza alcun successo! R segnala sempre che l'elemento "sì" non è specificato, ecc.

Come sempre, qualsiasi consiglio è apprezzato!

+5

Sembra che tu stia facendo le cose in modo troppo complicato. Perché non solo 'sprintf ("% 02d ", DB $ HOUR)'? Il punto principale di questa funzione è che riempie gli zeri iniziali con una lunghezza di 2 caratteri. – joran

+0

'sprintf' e' as.numeric' non sono all'interno della chiamata 'ifelse' come devono essere; c'è una parentesi chiusa prima di loro. Inoltre, stai mixando i tipi di ritorno all'interno di "ifelse" che porteranno alla promozione del tipo che potresti non aspettarti. –

+5

Infine, visto che sei relativamente nuovo qui e hai fatto una serie di domande, penso che sarebbe utile sottolineare che quando una risposta risolve il tuo problema, è molto utile fare clic sul segno di spunta accanto ad esso. Ciò migliora notevolmente il valore della domanda (e del sito) fornendo una chiara indicazione agli utenti futuri su quale risposta ha risolto il problema. Tieni sempre presente, tuttavia, che non sei obbligato ad accettare mai una risposta; è apprezzato, ma è sempre la tua scelta. – joran

risposta

37

semplicemente seguendo i consigli di commento @ di Joran,

DB <- data.frame(
HOUR = c(1, 10, 5, 20), 
ID = c(2, 4, 6, 6)) 

NHOUR <- sprintf("%02d",DB$HOUR) # fix to 2 characters 

cbind(NHOUR, DB) # combine old and newdata 
    NHOUR HOUR ID 
1 01 1 2 
2 10 10 4 
3 05 5 6 
4 20 20 6 

Aggiornamento 2013/01/21 23: 42: 00Z Ispirato da daroczig's performance test below, e perché volevo provare il microbenchmark package, ho aggiornato questa domanda con un piccolo test delle prestazioni di mio confronto tra le tre diverse soluzioni suggerite in questo thread.

# install.packages(c("microbenchmark", "stringr"), dependencies = TRUE) 
require(microbenchmark) 
require(stringr) 

SPRINTF <- function(x) sprintf("%02d", x) 
FORMATC <- function(x) formatC(x, width = 2,flag = 0) 
STR_PAD <- function(x) str_pad(x, width=2, side="left", pad="0") 

x <- round(runif(1e5)*10) 
res <- microbenchmark(SPRINTF(x), STR_PAD(x), FORMATC(x), times = 15) 

## Print results: 
print(res) 
Unit: milliseconds 
     expr  min  lq median  uq  max 
1 FORMATC(x) 623.53785 629.69005 638.78667 671.22769 679.8790 
2 SPRINTF(x) 34.35783 34.81807 35.04618 35.53696 37.1622 
3 STR_PAD(x) 116.54969 118.41944 118.97363 120.05729 163.9664 

### Plot results: 
boxplot(res) 

Box Plot of microbenchmark results

+0

Ancora una volta, ho complicato il lavoro ... pensavo che sprintf avrebbe messo uno zero davanti a qualsiasi valore!Mille grazie Joran, anche per il chiarimento in ifelse errori e grazie Eric per segnalare chiaramente il codice! – stefano

4

Soluzione alternativa:

> formatC(DB$HOUR, width = 2,flag = 0) 
[1] "01" "10" "05" "20" 

Aggiornamento: Ho appena eseguito un test rapido per il problema di prestazioni solo per documentare questa domanda

> library(microbenchmark) 
> SPRINTF <- function(x) sprintf("%02d", x) 
> FORMATC <- function(x) formatC(x, width = 2,flag = 0) 
> x <- round(runif(1e5)*10) 
> microbenchmark(SPRINTF(x), FORMATC(x), times = 10) 
Unit: milliseconds 
     expr  min  lq median  uq  max 
1 FORMATC(x) 688.35430 723.42458 767.06025 780.84768 878.4966 
2 SPRINTF(x) 31.29167 31.96052 35.75735 40.54656 147.6805 
+3

+1 questo è molto più chiaro dell'uso di 'sprintf'. perché usare la vecchia sintassi con un linguaggio moderno? –

+1

@MatthewPlourde, ti piacerebbe espandere il tuo punto? Cosa intendi per "molto più chiaro"? Nel mio rapido confronto tra 'sprintf' e' formatC' il primo è uscito molto più veloce, ma ovviamente la velocità non è tutto. –

+0

@EricFail no scherzo! la differenza di velocità è molto più grande di quanto avrei immaginato. Il mio entusiasmo per 'formatC' è stato mitigato. Se la velocità non è una preoccupazione, però, preferirei. Molti di coloro che lavorano con R non provengono da un background di programmazione. Sono sempre favorevole all'approccio con la massima leggibilità dal punto di vista del noob. ma hai anche un voto alto, perché è venerdì sera. –

9

Mi piace usare il pacchetto stringr:

DB$NHOUR <- str_pad(DB$HOUR, width=2, side="left", pad="0") 
+0

Vuoi approfondire perché ti piace il pacchetto stringr? –

+3

Eric, mi piace per la leggibilità. Quando qualcun altro sta leggendo il tuo codice e vedono 'gsub' o, in questo caso,' sprintf', non è molto chiaro cosa sta succedendo. Ma le funzioni di 'stringr' sono molto leggibili. Ad esempio, 'str_replace_all',' string_detect' o 'str_pad', è molto facile capire le operazioni eseguite. – rrs

+0

Grazie per aver risposto alla mia domanda, sono sempre curioso di imparare nuove cose. Forse perché provengo da un background non informatico e quindi non capisco perché alcuni codici abbiano una maggiore leggibilità rispetto ad altri. Per me gli elementi del pacchetto base sono spesso più _readable_. Inoltre, ho eseguito un piccolo test di velocità (usando 'proc.time()') e sulla mia macchina 'sprintf' è uscito quasi il doppio di' str_pad', ma di nuovo la velocità non è tutto. –

1

Simile al stringr, c'è stri_pad_left da stringi

library(stringi) 
stri_pad_left(str=DB$HOUR, 2, pad="0") 
# [1] "01" "10" "05" "20" 

Dovrebbe essere più o meno la stessa velocità-saggio. Ci sono funzioni di imbottitura simili per destra e entrambi i lati.