2015-12-02 13 views
5

Sono stato sconcertato da questo già alcune volte, quindi ecco una domanda inventata per gli altri che potrebbero inciampare sullo stesso problema.sostituzione elemento nel vettore di unità di griglia

Considerate questa unità griglia vettore,

a = unit(1:3, c("cm", "in", "npc")) 

voglio sostituire alcuni elementi con i nuovi valori. L'approccio naturale sarebbe,

a[1] = unit(2,"pt") 
a 
# [1] 2cm 2in 3npc 

Qualcosa è andato storto: solo il valore numerico è stato modificato, non l'unità. Perché? Cosa fare?

Modifica: Come indicato in una risposta di seguito, tali unità sono solo vettori numerici con attributi. Tuttavia, la loro progenie unit.arithmetic e unit.list deve essere considerata come soluzione per essere completamente generale (ad esempio per regolare le dimensioni dei pannelli degli oggetti ggplot). Considera questo vettore di unità,

(b = a + unit(1, "npc")) 
# [1] 1cm+1npc 2in+1npc 3npc+1npc 
# [1] "unit.arithmetic" "unit" 

Ora sostituire un elemento specifico è più difficile, poiché non sono più atomici.

risposta

2

Sembra che a sia solo un vettore atomico con alcuni attributi collegati ad esso. Pertanto, quando si utilizza a[1] = unit(2,"pt"), la nuova funzione unit crea un altro vettore atomico di lunghezza uno che sostituisce il valore di a[1]. Gli attributi rimangono intatti.

Quindi, qualcosa di simile sembra funzionare:

a[1] <- 2 
attr(a, 'unit')[1] <- 'pt' 

> a 
[1] 2pt 2in 3npc 
+0

Tuttavia, ho la sensazione che tu lo sappia già. – LyzandeR

+0

Ero nel mezzo di scrivere una risposta, ma sono rimasto bloccato a un certo punto. Il tuo approccio è corretto, ma temo non del tutto generale, poiché i vettori unitari possono anche contenere elementi più complessi, come l'unità.aritmetica: 'b = a + unità (1," npc ")'. Modificherò la domanda. – baptiste

+0

Posso vedere dove può andare storto con 'unit.arithmetics'. Se dici che il metodo '[<-' sarà difficile da implementare non ho motivo di non crederti. 'unit.list' sembra una buona soluzione tbh. – LyzandeR

3

A seguito di una discussione con Paul Murrell (e, in modo divertente, re-inventando quello che avevo figured out before), il problema sta nella mancanza di una Metodo [<- per unità di griglia. La soluzione a lungo termine sarebbe quella di implementare tali metodi, ma non è banale dal momento che le unità di griglia vengono fornite da fratelli come unità.aritmetica e unità.list, e la loro interazione può diventare difficile da comprendere.

La correzione più semplice, orientata all'utente, è quella di convertire tali vettori unitari in oggetti unit.list, che erediteranno un metodo accessor più come normali elenchi R. Questa promozione all'oggetto unit.list può essere eseguita con la funzione non importata grid:::unit.list().

a = unit(1:3, c("cm", "in", "npc")) 
b = grid:::unit.list(a) 
is.list(b) # check that indeed this is a list object, thanks @Josh O'Brien 
# [1] TRUE 
# so now we can use standard list methods 
b[[1]] = unit(2,"pt") 
b 
#[1] 2pt 2in 3npc 
+0

per favore spiegami perché il primitivo '[<-' ora fa la cosa giusta: io [non riesco a trovare un metodo per unit.list: S] (https://github.com/wch/r-source/ blob/b156e3a711967f58131e23c1b1dc1ea90e2f0c43/src/library/grid/R/unit.R) – baptiste

+0

Non ha bisogno di un metodo speciale. Questo è solo il comportamento predefinito '[<-' quando applicato a una lista (e un' unit.list' è una lista). –

+0

ma perché è una lista? (o come vedi che è uno). Immagino che abbia qualcosa a che fare con is.atomic (?) – baptiste

Problemi correlati