nom <- 100
nom
## [1] 100
6 Objectes
6.1 Introducció
Un objecte és un conjunt de dades que es troba emmagatzemat a R amb un nom determinat. Per emmagatzemar qualsevol objecte a R sempre utilitzarem el símbol <-
. A l’esquerra del símbol posarem el nom
de l’objecte i a la dreta les dades que volem emmagatzemar. Per exemple, amb el codi següent decidim emmagatzemar el nombre 100
en un objecte anomenat name
i a continuació el reproduïm a la consola:
Hi ha algunes coses que hem de saber en la creació d’objectes:
- Podem donar el nom que vulguem a un objecte. Les úniques limitacions és que no pot començar amb una xifra ni tampoc pot contenir espais1 ni cap dels símbols següents: ^, !, $, @, +, -, /, *.
1 Si volem posar-hi espais ho haurem d’envoltar amb aquests símbols `
`
. Per exemple, `Color de cabell`
.
<- 34 #donarà error
1object ! <- 44 #donarà error
objec<- 54 #donarà error
object first <- 64 #correcte
object_first `object first` <- 74 #correcte
- Si anomenem un objecte amb el nom d’un altre objecte creat prèviament, R ens sobreescriurà l’objecte sense avisar-nos prèviament.
name <- 100
name <- 50
name
## [1] 50
- R és sensible a les minúscules i a les majúscules, de manera que guardarà
Casa
icasa
com dos objectes diferents2.
2 Recomanem utilitzar minúscules sempre que es pugui i fer servir la barra baixa en cas de voler separar paraules per anomenar un mateix objecte.
Num <- 1001
num <- 101
Num
## [1] 1001
num
## [1] 101
- Quan guardem un objecte, no apareixerà res a la consola. Sabrem que l’objecte s’ha creat si observem el Global Environment o ho consultem amb les funcions
ls()
oobjects()
. Si volem veure reproduït l’objecte a la consola al mateix temps que el creem, haurem d’envoltar tot el codi entre parèntesi:
(bye <- 1)
## [1] 1
Principalment, treballarem amb tres tipus de dades a R: valors, vectors i marcs de dades3:
3 Hi ha d’altres classes d’objectes que també serveixen per emmagatzemar dades però que no estudiarem, com les matrius de dades (matrix) o els arrays.
6.2 Valors
Els valors són la unitat més petita que pot prendre un objecte d’R. Principalment trobem tres classes de valors:
6.2.1 Nombres
No cal definir gaire què és un nombre. Qualsevol nombre emmagatzemat a R quedarà registrat com a objecte numèric.
d <- 4
d
## [1] 4
R també podem emmagatzemar com a objecte el resultat d’una operació. L’únic que ens conserva és el resultat numèric de l’operació, tal com veiem si imprimim t
.
t <- (4 + 6 + 7) / 3
t
## [1] 5.666667
Podem fer operacions combinant valors numèrics i objectes que contenen valors numèrics. En el codi següent sumem l’objecte d
, l’objecte t
(que hem creat prèviament) i el nombre 1
:
d + t + 1
## [1] 10.66667
Fixem-nos que els objectes d
i t
han quedat guardats al Global Environment. També podem consultar en qualsevol moment els objectes que hem creat amb la funció ls()
.
6.2.2 Caràcters
A R podem guardar qualsevol text que contingui caràcters, nombres i altres símbols. Sempre haurem de posar el text entre cometes (" "
).
z <- "Obama"
Quan emmagatzemem caràcters és molt important saber que R és sensible a les majúscules. Si volem crear un marc de dades sobre els presidents dels Estats Units, hem de saber que Obama
no és el mateix que OBama
ni tampoc que OBAMA
. Fem la prova:
És un error comú copiar text d’R a programes com Word que, segons com estiguin configurats, poden canviar automàticament alguns símbols del text. El cas més habitual és el de les cometes, que ens les arrodoneix. Fixeu-vos amb la diferència:
-
"Cara"
: R entendrà que és un valor en forma de caràcter i el reproduïrà sense problema. -
“Cara”
: R ens donarà error perquè les cometes són arrodonides.
"Obama" == "OBama"
## [1] FALSE
"OBAMA" == "OBAMA"
## [1] TRUE
En el primer cas li preguntem si Obama
i OBama
eren el mateix valor i ens ha respost que no, creant-nos com a resultat el valor lògic FALSE
. En el segon cas ens ha confirmat que OBAMA
i OBAMA
són efectivament el mateix valor. Aquesta operació que acabem de fer és molt important com a punt de partida per comprendre l’utilitat dels valors lògics, que veurem a continuació.
6.2.3 Lògics
Per lògica, deia Aristòtil, les idees només poden ser verdaderes o falses. No hi ha mitges veritats. De la mateixa manera, els valors lògics només poden ser veritat o fals. Els podem emmagatzemar introduint TRUE
(o el símbol T
) o FALSE
(o el símbol F
).
blonde <- T
blonde
## [1] TRUE
thin <- F
thin
## [1] FALSE
Molts de vosaltres relacionareu els valors lògics amb les classes de filosofia de l’institut. I, efectivament, els utilitzarem de la mateixa manera. Però també és important saber que els operadors lògics formen part del nostre dia a dia. Els utilitzem constantment quan fem cerques a Google o Instagram. Ho veurem més endavant, a l’apartat de vectors lògics. Per ara només necessitem saber que existeixen. I que la seva lògica és un xic complicada, però que ens seran de gran utilitat per treballar amb R.
6.3 Vectors
Una cadena de valors forma un vector. Cada vector només pot emmagatzemar valors d’una mateixa classe. Per tant, als vectors que emmagatzemen nombres els direm vectors numèrics, als que guarden caràcters els direm vectors de caràcter i als que emmagatzemen valors lògics els direm vectors lògics. A partir d’aquests tipus de vectors, també en podem crear d’altres. En aquest mòdul, en total, n’estudiarem sis: vectors numèrics, enters, de caràcter, factors, lògics i de data.
Quan creem un vector, sempre concatenarem els valors, separats per comes, dins de la funció c()
, com veiem en el següent exemple.
És molt important tenir present l’estructura bàsica d’un vector. Si ens descuidem una coma entre valors o tancar el parèntesi, R ens donarà error quan executem l’operació.
nom_objecte <- c(valor1, valor2, valor3, valor4)
Sempre serà preferible que els noms dels objectes tinguin alguna cosa a veure amb el seu contingut. Per exemple, si creem un vector amb noms de països, ens serà més útil anomenar-lo countries
que no pas simplement vector
o names
, que no ens aporta cap informació substantiva sobre el seu contingut.
En els següents subapartats crearem vectors de longitud cinc, que significa que estan formats per cinc valors. Però hem de saber que podem crear vectors d’un sol valor fins a vectors d’una longitud igual a milions de valors.
6.3.1 Vectors numèrics
El vector numèric (que també podem anomenar doble) emmagatzema nombres. Per crear-ne un, només hem de separar el valor de cada nombre per una coma. En el codi següent hem creat un objecte de nom numeric
de longitud cinc. Si volem que els nombres tinguin decimals, haurem de marcar els decimals amb un punt com en el codi num_dec
.
També podem incloure a dins d’un vector objectes que haguem creat anteriorment i que continguin nombres. En el següent exemple, per crear l’objecte num_mix
utilitzem els objectes e
i d
que havíem creat anteriorment.
e <- 3
num_mix <- c(1, 3, e, 4, d)
num_mix
## [1] 1 3 3 4 4
Una opció ràpida per crear vectors numèrics que continguin seqüències correlatives de valors és utilitzar el símbol :
. En aquest exemple, el primer valor del vector prendrà el valor de l’objecte e
i la resta seran els nombres correlatius entre 4 i 7. Per tant, serà com si introduíssim c(3, 4, 5, 6, 7)
, però estalviarem codi.
num_points <- c(e, 4:7)
num_points
## [1] 3 4 5 6 7
Els vectors numèrics permeten fer operacions matemàtiques com sumar (+
), restar (-
), multiplicar (*
) o dividir (/
). Segons la longitud dels vectors, podem fer dos tipus d’operacions:
Què passa si, per exemple, fem una operació entre un vector amb longitud 5 i un vector amb longitud 2?
numeric - 1:2
## Warning in numeric - 1:2: longer object length is not a multiple of shorter
## object length
## [1] 3 3 5 5 7
Fixeu-vos que ha completat l’operació, repetint la seqüència de valors del vector més petit (1 2 1 2 1
) fins a igualar-se amb la longitud del vector més gran.
-
Vector amb un nombre: Ens fa l’operació de tots els valors del vector pel nombre en qüestió. En el següent cas, dividirà cada valor del vector
num_mix
entre 10.
num_mix / 10
## [1] 0.1 0.3 0.3 0.4 0.4
-
Entre vectors d’igual longitud: Quan fem una operació matemàtica entre dos o més vectors de la mateixa longitud, R ens farà l’operació entre els valors que tinguin la mateixa posició en el vector. Per exemple, si sumem els vectors
numeric
inum_dec
, R sumarà el primer valor denumeric
amb el primer valor denum_dec
, el segon valor denumeric
amb el segon valor denum_dec
, i així successivament.
numeric
## [1] 4 5 6 7 8
num_dec
## [1] 54.98 55.97 76.58 47.33 82.24
numeric + num_dec
## [1] 58.98 60.97 82.58 54.33 90.24
Podem fer tantes operacions matemàtiques amb tants vectors com vulguem, sempre i quan respectin les normes descrites anteriorment. En canvi, si fem operacions amb vectors que tenen diferent longitud ens retornarà un avís.
6.3.2 Vectors enters
Una variant del vector numèric és el vector enter. Aquest tipus de vector, a diferència del numèric, no pot emmagatzemar decimals. És un vector que no utilitzarem gaire sovint, però que val la pena conèixer perquè forma la base d’altres tipus de vectors. Existeixen dues formes de crear-lo:
A. Situant una L
al davant de cada nombre.
integer_L <- c(3L, 6L, 7L, 5L, 9L)
integer_L
## [1] 3 6 7 5 9
B. Utilitzant la funció as.integer()
.
integer_F <- as.integer(c(2022, 2021, 2021, 2021, 2020))
integer_F
## [1] 2022 2021 2021 2021 2020
6.3.3 Vectors de caràcter
El vector de caràcter (també anomenats strings) emmagatzemen diferents valors de caràcter. Per tant, com ja hem vist anteriorment, per crear-los haurem d’envoltar cada valor amb les cometes (" "
) com veiem en el següent exemple.
Un error molt comú és descuidar-se una cometa quan creem un vector de caràcter. Això farà que R ens doni error quan intentem reproduir l’operació. És fàcil adonar-nos de l’error perquè els caràcters deixen d’estar il·luminats amb color diferent:
c("C", "J", G", "C", "N")
character <- c("Colombia", "Japan", "Germany", "Chile", "New Zealand")
Els vectors de caràcter no es restringeixen només als caràcters alfabètics. Hi podem emmagatzemar nombres també, però com que estaran emmagatzemats com a caràcters no tindran les propietats dels nombres i no hi podrem aplicar operacions matemàtiques.
Als vectors de caràcter hi podem introduir tota mena de símbols no alfanumèrics.
mingle <- c("4$", "אַפֿגהאַניסטאַן", "الإحصاء", "%16", "統計学3")
6.3.4 Factors
Si despullem el factor que hem creat amb la funció unclass(factor)
, podem veure exactament quina és la seva composició real.
unclass(factor)
## [1] 1 2 3 1 4
## attr(,"levels")
## [1] "America" "Asia" "Europe" "Oceania"
En realitat, un factor és un vector enter que té assignada una etiqueta a cadascun dels seus nombres. Així, el nombre 1 té assignada l’etiqueta "America"
, el nombre 2 l’etiqueta "Asia"
, i així successivament.
Una variant dels vectors de caràcter són els factors. De fet, el factor és una classe de vector que, per les seves característiques, es troba entremig del vector de caràcter i el vector enter. Formalment, direm que un factor és un vector enter que pot emmagatzemar caràcters. Aquesta definició costa d’entendre i no ens servirà de gaire ara mateix, però més endavant comprendrem la utilitat dels factors. Per ara, només ens cal saber que es crea si envoltem el concatenat amb la funció factor()
6.3.5 Vectors lògics
Els vectors lògics emmagatzemen valors lògics i per tant només poden prendre dos valors: TRUE
o FALSE
.
logic <- c(TRUE, FALSE, FALSE, TRUE, FALSE)
Sense adonar-nos-en, utilitzem diàriament operadors lògics. Quan busquem pàgines web o fotografies a Google, els operadors lògics es posen a funcionar. Com a exemple, hem creat tres vectors, dos de caràcter i un numèric, amb les caràcterístiques de cinc personatges del món de Hollywood.
Quan busquem per Johnny Depp, Google busca per totes les seves bases de dades i retorna TRUE
totes aquelles pàgines que coincideixen amb el nom "Johnny Depp"
.
act == "Johnny Depp"
## [1] TRUE FALSE FALSE FALSE FALSE
També podem preguntar pels personatges nascuts a partir de 1975. En aquesta mini-base de dades que tenim, R rastrejarà la informació a born
i ens dirà quins valors són veritat (TRUE
).
born > 1975
## [1] FALSE FALSE TRUE TRUE FALSE
Amb els vectors lògics podrem fer, més endavant, combinacions més sofisticades de cerca. La majoria de combinacions seran utilitzant el símbol |
per preguntar-nos si alguna de les característiques que demanem és present a la base de dades, i utilitzant el símbol &
per preguntar-nos si totes les característiques que demanem són presents. Vegem dos exemples:
Hem preguntat per aquells personatges de Hollywood que tenen el cabell ros o bé (símbol |
) que han nascut més tard de 1975.
blond_or_1975 <- hair == "blond" | born > 1975
blond_or_1975
## [1] FALSE TRUE TRUE TRUE FALSE
En el segon, el tercer i el quart valor, alguna de les dues condicions és certa.
Hem preguntat per aquells personatges de Hollywood que tenen el cabell ros i (símbol &
) han nascut més tard de 1975.
blond_and_1975 <- hair == "blond" & born > 1975
blond_and_1975
## [1] FALSE FALSE FALSE TRUE FALSE
Només el quart valor compleix totes les condicions.
A aquestes alçades, potser encara no hi trobarem gaire la utilitat als vectors lògics, així que no ens aturarem a explicar gaire cosa més. Però més endavant comprovarem que són un tipus de vector essencial en la gestió de dades.
6.3.6 Vectors de data
I finalment, tenim els vectors de data. Com hem pogut suposar, aquests vectors emmagatzemen dates. La manera més senzilla de crear-los és introduir les dates en un vector de caràcter, de manera que a cada valor hi figuri primer amb l’any, després el mes i finalment el dia (YYYY/MM/DD). La funció as.Date()
ens convertirà aquest vector en un vector de data.
Si despullem el vector de data amb la funció unclass(date)
veurem la seva composició real.
unclass(factor)
## [1] 1 2 3 1 4
## attr(,"levels")
## [1] "America" "Asia" "Europe" "Oceania"
Sorpresa, els vectors de data són en realitat un vector numèric. R assigna a cada nombre un dia, mes i any concret. Fixeu-vos que la data de 2018 correspon amb el nombre més baix i el de 2021 amb el nombre més alt. Sabríeu trobar quin és l’any 0?
Tampoc ens detindrem ara a estudiar a fons els vectors de data, però hem de saber que ens poden ser útils per fer operacions entre moments del temps determinats. Per exemple, amb l’operació següent sabem ràpidament que hi ha 1015 dies de diferència entre el 15 de març de 2018 i el 23 de febrer de 2021.
6.3.7 Resum vectors
Els errors més comuns de codi quan creem vectors són:
c(4, 6 7, 8)
c(TRUE, FALSE, TRUE
c("France, "Spain", "UK")
Sabries identificar els errors a cada exemple? Trobaràs la solució al següent desplegable.
En el primer cas no hem separat el 6 i el 7 amb una coma. En el segon cas no hem tancat parèntesi. En el tercer cas no hem tancat la cometa de France.
Un bon resum d’aquesta secció el trobareu si consulteu el vostre Global Environment, on heu anat creant vectors de diferents classes. Aquí en podeu veure una selecció. Com podeu comprovar, el Global Environment mostra el nom de l’objecte, seguit de la classe, la longitud i una mostra dels seus primers valors.
La classe o el tipus de cada objecte es poden consultar amb les funcions class()
o typeof()
. A la taula 6.1 tenim un resum dels vectors que hem vist i les seves característiques. Hi ha petites diferències entre classe i tipus d’objecte, però per ara no són gaire rellevants. Només les explorarem més endavant quan sigui necessari.
Classe | Tipus | Exemple |
---|---|---|
Caràcter | Caràcter | c("b", "c", "d") |
Factor | Enter | factor(c("b", "c", "d")) |
Enter | Enter | c(10L, 6L, 12L) |
Numèric | Doble | c(1.1, 3.5, 10.2) |
Data | Doble | as.Date(c("2019/06/04", "2019/11/02", "2020/01/23")) |
Lògic | Lògic | c(FALSE, TRUE, FALSE) |
6.4 Marc de dades
Un conjunt de vectors d’igual longitud forma un marc de dades. Per crear-lo, només cal introduir, separats per comes, diversos vectors com a arguments successius de la funció tibble()
4 del paquet dplyr
.
4 Per crear marcs de dades també existeix la funció data.frame()
però és una mica antiquada i no l’estudiarem.
tibble(vector1, vector2, vector3, vector4...)
Per crear un marc de dades, és indispensable que tots els vectors tinguin la mateixa longitud. Si no tenen la mateixa longitud, ens donarà error.
country <- c("Colombia", "Japan", "Germany", "Chile", "New Zealand")
year <- as.integer(c(2022, 2021, 2021, 2021, 2020))
date <- as.Date(c("2022/05/29", "2021/10/31", "2021/09/26", "2021/11/21", "2020/10/17"))
turnout <- c(54.98, 55.97, 76.58, 47.33, 82.24)
continent <- factor(c("America", "Asia", "Europe", "America", "Oceania"))
presidential <- c(TRUE, FALSE, FALSE, TRUE, FALSE)
elections <- tibble(country, year, date, turnout, continent, presidential)
Si imprimim el marc de dades elections
, la consola ens retornarà el resultat que observem a continuació.
elections
## # A tibble: 5 × 6
## country year date turnout continent presidential
## <chr> <int> <date> <dbl> <fct> <lgl>
## 1 Colombia 2022 2022-05-29 55.0 America TRUE
## 2 Japan 2021 2021-10-31 56.0 Asia FALSE
## 3 Germany 2021 2021-09-26 76.6 Europe FALSE
## 4 Chile 2021 2021-11-21 47.3 America TRUE
## 5 New Zealand 2020 2020-10-17 82.2 Oceania FALSE
Com podem observar, un marc de dades és un tipus d’objecte que guarda les dades en dues dimensions: les files i les columnes.
- Les files seran tan llargues com la longitud de cada un dels vectors.
- Les columnes seran tan amples com el nombre de vectors que conformen el marc de dades.
No ens serà gens difícil comptar que el marc de dades elections
està format per cinc files i sis columnes. Aquest càlcul és relativament fàcil de fer en marcs de dades petits, però la cosa es complica en marcs de dades de dimensions descomunals. Per sort, les dimensions ens apareixen impreses al principi del marc de dades (veiem: A tibble: 5 x 6
) anterior i també tenim altres funcions, com dim()
que ens ho calculen.
Existeix una segona manera de crear marcs de dades, que és posant els vectors directament a dins de la funció tibble()
. En aquest cas, a dins de cada argument hi haurem de situar el nom que volem que tingui el vector, seguit del símbol igual =
i el vector corresponent. L’estructura és la següent:
tibble(nom_vector1 = c(valor1, valor2, valor3, etc.),
nom_vector2 = c(valor1, valor2, valor3, etc.),
nom_vector2 = c(valor1, valor2, valor3, etc.))
Seguint aquesta estructura, podem crear exactament el mateix marc de dades que hem creat anteriorment a l’objecte elections
. Aquest procediment ens evita haver de crear un objecte per a cada vector, de manera que mantenim el Global Environment més net.
elections <- tibble(country = c("Colombia", "Japan", "Germany", "Chile", "New Zealand"),
year = as.integer(c(2022, 2021, 2021, 2021, 2020)),
date = as.Date(c("2022/05/29", "2021/10/31", "2021/09/26", "2021/11/21", "2020/10/17")),
turnout = c(54.98, 55.97, 76.58, 47.33, 82.24),
continent = factor(c("Europe", "Asia", "Europe", "America", "Oceania")),
presidential = c(TRUE, FALSE, FALSE, TRUE, FALSE))
Quan vulguem fer servir el vector d’un marc de dades, utilitzarem el símbol $
. Així, prenent com a referència el marc de dades elections
, si volem consultar el vector country
farem servir el codi següent:
elections$country
## [1] "Colombia" "Japan" "Germany" "Chile" "New Zealand"
Recordeu que per guardar un objecte hem d’utilitzar el símbol <-
i que amb els vectors numèrics només podem fer operacions amb altres vectors de la mateixa longitud o amb un altre valor numèric. Seguint aquesta lògica, podrem posar les xifres del vector turnout
en tant per u si dividim el vector pel valor 100
i el guardem al vector amb el mateix nom. Amb aquesta acció sobreescriurem el contingut anterior del vector.
elections$turnout <- elections$turnout / 100
elections$turnout
## [1] 0.5498 0.5597 0.7658 0.4733 0.8224
Si imprimim de nou elections
veurem el resultat de la modificació.
Anteriorment, hem vist que un vector només pot emmagatzemar valors d’un sol tipus. Heu provat què passa quan intentem crear un vector amb valors de diferent tipus? Sorprenentment, R no dona error sinó que ens crea el vector. El que passa és una cosa que se’n diu coerció de les dades, que significa la conversió automàtica dels valors d’un tipus als valors d’un altre tipus. Vegem-ne alguns exemples:
- Combinem un valor numèric i un valor lògic.
- Combinem un valor de caràcter i un valor lògic.
- Combinem un valor numèric i un valor de caràcter.
- Combinem un valor numèric, un valor de caràcter i un valor lògic.
Si us heu fixat, la lògica que segueix és la següent: Caràcter > Numèric > Lògic. Entre caràcters i nombres, R crearà un vector de caràcter. Entre nombres i valors lògics, R crearà un vector numèric. Això és així perquè és la manera que ens permet conservar el màxim d’informació. TRUE
i FALSE
els podem guardar com a 1
i 0
en un vector numèric, de manera que no perdem la pista sobre què era originàriament cada valor. En canvi, no tenim manera de guardar els nombres 100
i 59
en un vector lògic sense perdre informació. Finalment, com que en un vector de caràcter hi podem guardar qualsevol cosa, un valor de caràcter sempre guanyarà la coerció contra qualsevol altre valor.