miércoles, 2 de septiembre de 2015

Selección de elementos de un vector de acuerdo a un patrón

[Lenguajes: R]

Problema

Se requiere seleccionar algunos elementos de un vector de acuerdo con un patrón repetitivo. Como ejemplo, se quiere seleccionar el tercero y cuarto elementos de cada diez elementos en secuencia.

Para ilustrar el problema, supongamos que se tiene un vector que consiste en 55 numeros, empezando con el 101, como sigue:

(v <- 101:155)
##  [1] 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
## [18] 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
## [35] 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
## [52] 152 153 154 155

De ahí se quieren seleccionar, como se dijo, el tercer y cuarto elementos de cada diez elementos en la secuencia, de modo que se produzca una salida como la que se muestra a continuación:

##  [1] 103 104 113 114 123 124 133 134 143 144 153 154

Solución

En R, los vectores de lógicos se pueden utilizar para indexar otro vector, a manera de una máscara que prende o apaga los elementos del vector que se seleccionan a la salida. Así, por ejemplo, si queremos seleccionar los elementos impares en el vector v, se puede hacer como se muestra:

# Los elementos de v que no son divisibles por 2:
(ii <- v %% 2) # operación módulo
##  [1] 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
## [36] 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
# Convertimos ii a lógico
ii <- as.logical(ii)
# Y los impares son:
v[ii]
##  [1] 101 103 105 107 109 111 113 115 117 119 121 123 125 127 129 131 133
## [18] 135 137 139 141 143 145 147 149 151 153 155

Cuando el vector indexador de otro vector en R es lógico, y es de un tamaño menor al vector indexado, R lo recicla, o sea, repite la secuencia y esto es algo de lo que podemos sacar ventaja para resolver nuestro problema original; pero antes, veamos que la salida anterior, si, como es el caso, v es una secuencia de números enteros conocida, se puede producir de manera muy simple, como sigue:

v[c(TRUE, FALSE)]
##  [1] 101 103 105 107 109 111 113 115 117 119 121 123 125 127 129 131 133
## [18] 135 137 139 141 143 145 147 149 151 153 155

Si usamos este mismo comportamiento, podemos producir la máscara repetitiva del patrón, de la manera siguiente:

# Un vector lógico de 10 elementos inicializados como FALSE
ii <- logical(10)
# "Prendemos" los elementos 3 y 4 de la máscara
ii[c(3,4)] <- TRUE
# La "máscara"" es:
ii
##  [1] FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE

Ahora, simplemente se usa esa máscara como un índice del vector original v:

v[ii]
##  [1] 103 104 113 114 123 124 133 134 143 144 153 154

Y el problema ha quedado resuelto!

Notemos que no hay restricción en la clase de elementos de vector que se indexa. Hagamos, por ejemplo, un vector de 55 letras seleccionadas aleatoreamente:

(aa <- sample(letters, 55, replace=TRUE))
##  [1] "l" "s" "k" "i" "t" "f" "s" "d" "g" "d" "g" "b" "q" "w" "u" "u" "l"
## [18] "k" "v" "p" "r" "j" "h" "z" "q" "f" "d" "m" "y" "p" "z" "t" "j" "l"
## [35] "d" "a" "s" "c" "l" "q" "z" "m" "m" "e" "t" "l" "n" "f" "f" "p" "o"
## [52] "c" "a" "q" "y"

Seleccionemos de ese vector, igual, el tercero y cuarto elementos de cada diez; para ello, podemos utilizar la misma máscara generada previamente (ii):

aa[ii]
##  [1] "k" "i" "q" "w" "h" "z" "j" "l" "m" "e" "a" "q"

Si quieres ver este mismo post en mis publicaciones de Rpubs:


jueves, 30 de julio de 2015

La latosa coma decimal europea

[Lenguajes: R]

Problema

La información real proviene de fuentes heterogéneas y como tal, puede contener errores debidos a la mala definición de requerimientos a los responsables de las funtes de información, o a errores conceptuales o de configuración del software empleado en la recabación de información.

Por ejemplo, inexplicablemente, algunas versiones de Microsoft Excel traen como formatos de entrada de números, en el continente americano, la europea coma decimal, en lugar del usual y legal punto decimal. Lo peor del caso, es que, en algún levantamiento de información, sin atender a este aspecto, se conjunta toda la información levantada con diferentes formatos en una sola columna de un archivo, dando lugar a una expresión heterogénea de los números; lo cual puede producir verdaderos dolores de cabeza, sobre todo si el volumen de información es inmenso. ¿Cómo se puede manejar este tipo de errores en R?

Para analizar este problema más de cerca, propongo el siguiente ejemplito de juguete:

Se hizo un censo, y la información se conjuntó en una tabla de Excel con dos columnas, que se leyó en R de la manera siguiente:

tt <- read.csv2("heterogeneo.csv", stringsAsFactors=F)
tt
##   uno    dos
## 1   a    1.2
## 2   b    3.5
## 3   c    6.4
## 4   d   -7.2
## 5   e    5,3
## 6   f    6.8
## 7   g  0,001

Detección del problema

Se nota primeramente que hemos leído la infomación bloqueando la interpretación de los strings de caracteres como factores; esto es, precisamente para tratar los strings de caracteres justamente como strings de caracteres en todo el desarrollo del problema.

Se espera que la columna “dos” de la tabla leída sea de tipo numeric; veamos, sin embargo, qué es lo que resulta al consultar su clase:

## La clase de la columna dos:
class(tt$dos)
## [1] "character"

Esto indica que la lectura no se ha hecho adecuadamente. Al revisar con detalle, se observa que en los renglones 5 y 7 se han puesto comas decimales en lugar de puntos decimales. Esto pudiera no ser evidente en una tabla con un elevado número de renglones. En seguida muestro cómo detectar los lugares exactos del problema:

# Se forza una conversión a "numeric"
nn <- as.numeric(tt$dos)
## Warning: NAs introducidos por coerción
# La operación anterior arroja un **Warning**, pero no interrumpe los
# cálculos.
# En un gran número de renglones la siguiente impresión, posiblemente
# no mostraría los sitios del problema:
nn
## [1]  1.2  3.5  6.4 -7.2   NA  6.8   NA
# Para saber los índices (renglones) exactos de los elementos que han
# causado el problema, se hace así:
is.na(nn) # Vector de lógicos
## [1] FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE
which( is.na(nn) ) # Así se convierte el vector de lógicos a índices
## [1] 5 7

NOTA: El uso de la función which() aplicable a los vectores booleanos se ha ilustrado en un post previo: Transformación de selecciones booleanas en selecciones indexadas.

Solución

La solución del problema es sencilla. Se parte del hecho de que la columna se ha leído como un string de caracteres. La clave es simplemente convertir los caracteres “,” a “.”, en los strings que conforman el vector, de la siguiente manera:

# Guardamos el resultado en la misma columna:
tt$dos <- sub(",", ".", tt$dos, fixed = TRUE)
tt$dos
## [1] " 1.2"   " 3.5"   " 6.4"   " -7.2"  " 5.3"   " 6.8"   " 0.001"

En seguida se ejecuta la conversión de toda la columna a numeric:

# Nuevamente guardamos el resultado en la misma columna:
tt$dos <- as.numeric(tt$dos)
tt
##   uno    dos
## 1   a  1.200
## 2   b  3.500
## 3   c  6.400
## 4   d -7.200
## 5   e  5.300
## 6   f  6.800
## 7   g  0.001
# Y la clase de la columna es:
class(tt$dos)
## [1] "numeric"

Con esto se concluye el ejemplo.


Si quieres ver este mismo post en mis publicaciones de Rpubs:


viernes, 17 de julio de 2015

Transformación de selecciones booleanas a selecciones indexadas

[Lenguajes: R]

Problema

En R, una de las técnicas para seleccionar porciones de conjuntos de datos a partir de condiciones dadas, es por medio de la utilización de índices booleanos creados a partir de expresiones lógicas. Por ejemplo, si tenemos un vector numérico como el que sigue:

V <- c(18, 8, 5, 41, 8, 7)
V
## [1] 18  8  5 41  8  7

y se quiere saber para cuáles de estos números, su valor absoluto menos nueve es menor que tres, lo podemos hacer con la expresión lógica:

( L <- abs(V - 9) <= 3 )
## [1] FALSE  TRUE FALSE FALSE  TRUE  TRUE

Esta expresión, es un vector lógico, paralelo al original, que indica con el valor TRUE, los correspondientes valores de V que cumplen con la condición.

Para saber cuáles son los valores que cumplen con la condición, simplemente se usa como índice el vector lógico resultante, L, en el vector numérico original, V:

V[L]
## [1] 8 8 7

Sin embargo, a veces, estmos realmente interesados en los índices numéricos de los elementos de V que cumplen con la condición, esto es, 2, 5 y 6.

Solución

La función which() transforma los índices booleanos a índices numéricos enteros, de la siguiente manera:

which(L)
## [1] 2 5 6

Un resultado similar se puede obtener si se usa una secuencia numérica, de 1 hasta el número de elementos en V, esto es, 1, 2, …, length(V), y se sustraen los elementos marcados como verdaderos en L, como se muestra a continuación:

seq_along(V)[L]
## [1] 2 5 6
# o también:
seq_along(L)[L]
## [1] 2 5 6

Si quieres ver este mismo post en mis publicaciones de Rpubs:


viernes, 10 de julio de 2015

Gráfico de caída libre

[Lenguajes: R]

Problema

Dado que el lenguaje R tiene la posibilidad de manejar vectores de una manera muy natural, los problemas de la mecánica clásica se pueden resolver de manera bastante sencilla, con la posibilidad, incluso, de presentar los resultados gráficos muy atractivos.

En seguida propongo un problema sencillo.

Problema de mecánica clásica

De un edificio, a una altura de 15 m, se ha lanzado con un ángulo de 50 grados, un proyectil a una velocidad de 7 m/s. ¿Cuáles serán las alturas (coordenadas y) del proyectil a cada 0.5 m de distancia horizontal desde donde se lanzó y hasta los 11 m?

Se requiere además hacer una gráfica que muestre la trayectoria del proyectil.

Solución

Las ecuaciones físicas que gobiernan este fenómeno son las siguientes:

(Desgraciadamente Blogger falla en desplegar las ecuaciones de abajo, sugiero que vean este post en el PEGOTE de Rpubs , abajo.)

\[x=v_{0x}t+x_{0}\] \[y=-\frac{1}{2}gt^{2}+v_{0y}t+y_{0}\]
Aquí, $g$ es la aceleración de la gravedad, el parámetro \(t\) se refiere al tiempo, y la velocidad está descompuesta en sus componentes: \(v_{0x}\) y \(v_{0y}\).
g <- 9.81 # aceleracion gravedad
x0 <- 0   # x inicial
y0 <- 15  # y inicial
vi <- 7  # velocidad inicial
alphaD <- 50 # angulo-grados

y para encontrar las componentes de la velocidad:

# Se convierte el ángulo a radianes:
alpha <- (pi/180)*alphaD # angulo-radianes
(vox <- vi*cos(alpha)) # componente x de velocidad inicial
## [1] 4.499513
(voy <- vi*sin(alpha)) # componente y de velocidad inicial
## [1] 5.362311

Con esto es suficiente para proceder con el problema. Primeramente se obtienen las x para las que se desea hacer el cálculo, de la siguiente forma:

# desde 0 hasta 11 de 0.5 en 0.5:
las.x <- seq(from=0, to=11, by=0.5)

Nótese que en las fórmulas que gobiernan el fenómeno, dadas anteriormente, no se tiene \(y\) en función de \(x\), sino que las dos coordenadas dependen del parámetro \(t\), esto es, del tiempo. Para resolver este asunto simplemente se despeja en parámetro \(t\), en la ecuación de \(x\), y obtenemos:

\[t=(x-x_{0})/v_{0x}\]

Así, obtenemos los valores de \(t\) correspondientes a las \(x\), usando esta fórmula en R:

las.t <- (las.x - x0)/vox

Finalmente, encontramos las y correspondientes a las t, recien encontradas, aplicando la fórmula para y:

las.y <- -(g/2)*las.t^2 + voy*las.t + y0
# Los resultados:
las.x
##  [1]  0.0  0.5  1.0  1.5  2.0  2.5  3.0  3.5  4.0  4.5  5.0  5.5  6.0  6.5
## [15]  7.0  7.5  8.0  8.5  9.0  9.5 10.0 10.5 11.0
las.y
##  [1] 15.0000000 15.5353081 15.9494790 16.2425125 16.4144087 16.4651675
##  [7] 16.3947891 16.2032734 15.8906203 15.4568299 14.9019022 14.2258372
## [13] 13.4286349 12.5102953 11.4708183 10.3102040  9.0284524  7.6255636
## [19]  6.1015373  4.4563738  2.6900730  0.8026348 -1.2059407

El gráfico se podría hacer con los resultados anteriores utilizando la función plot(), con su parámetro type=“l”, que corresponde a líneas, de la siguiente manera:

plot(las.x, las.y, type="l")

plot of chunk unnamed-chunk-6

Nótese la diferencia de escalas en los ejes. Un método más elegante consiste en utilizar la función curve(), diseñada específicamente para graficar funciones. Para ello, los cálculos anteriores deben ser transformados a funciones, de la manera que se muestra a continuación:

ft <- function(x) (x-x0)/vox # tiempo para una x dada
# Las 'y' en función de x:
y <- function(x) {t <- ft(x); -(g/2)*t^2 + voy*t + y0}
curve(y,xlim=c(0,11),asp=1, main="Lanzamiento proyectil")
abline(v=0,col="red") # linea vertical x=0
abline(h=0,col="red") # linea horizontal y=0
points(x0,y0,pch=19, col="red") # Punto inicial

plot of chunk unnamed-chunk-7


Si quieres ver este mismo post en mis publicaciones de Rpubs:


jueves, 9 de julio de 2015

Operaciones entre matrices paralelas 1

[Lenguajes: R]

Problema

Se tiene una lista de matrices, todas de las mismas dimensiones y se quiere realizar operaciones estadísticas, como la media o la desviación estándar, elemento a elemento. Por ejemplo, la media de todos los elementos con índices [1,1], [2,1], … [i,j], etc. Esto es, el resultado será una matriz, con las mismas dimensiones que cada una de las originales, pero que contendrá la media de los correspondientes elementos en cada una de las matrices.

Para entender el problema, propondré un ejemplo, como sigue:

a <- matrix(1:9, nrow=3)
b <- matrix(2:10, nrow=3)
c <- matrix(3:11, nrow=3)
d <- matrix(4:12, nrow=3)
L <- list(a,b,c,d)
L
## [[1]]
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
## 
## [[2]]
##      [,1] [,2] [,3]
## [1,]    2    5    8
## [2,]    3    6    9
## [3,]    4    7   10
## 
## [[3]]
##      [,1] [,2] [,3]
## [1,]    3    6    9
## [2,]    4    7   10
## [3,]    5    8   11
## 
## [[4]]
##      [,1] [,2] [,3]
## [1,]    4    7   10
## [2,]    5    8   11
## [3,]    6    9   12

En el caso mostrado, la matriz resultante tendría igualmente 3 renglones y 3 columnas y si la operación que se desea efectuar es la media, por ejemplo, el elemento [3,1] de esa matriz debería contener el siguiente valor:

mean(c(L[[1]][3,1], L[[2]][3,1], L[[3]][3,1], L[[4]][3,1]))
## [1] 4.5
# O sea mean(c(3,4,5,6))

Esto, desde luego debería hacerse para todos y cada uno de los elementos. ¿Cómo hacer esta operación de manera sencilla?

Solución

El primer paso consiste en convertir la lista a un arreglo de 3 dimensiones, de la siguiente manera:

simplify2array(L)
## , , 1
## 
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
## 
## , , 2
## 
##      [,1] [,2] [,3]
## [1,]    2    5    8
## [2,]    3    6    9
## [3,]    4    7   10
## 
## , , 3
## 
##      [,1] [,2] [,3]
## [1,]    3    6    9
## [2,]    4    7   10
## [3,]    5    8   11
## 
## , , 4
## 
##      [,1] [,2] [,3]
## [1,]    4    7   10
## [2,]    5    8   11
## [3,]    6    9   12

Notemos ahora que, en este arreglo, los dos primeros índices corresponden a los índices de las matrices originales y el tercer índice, correspondería al orden de cada una de las matrices. De modo que lo que se tiene que hacer es aplicar una operación marginal mediante la función apply(), donde el margen donde queremos los resultados está dado por los índices 1 y 2.

Entonces el resultado que esperamos lo obtenemos fácilmente de la siguiente manera:

apply(simplify2array(L), MARGIN=1:2, FUN=mean)
##      [,1] [,2] [,3]
## [1,]  2.5  5.5  8.5
## [2,]  3.5  6.5  9.5
## [3,]  4.5  7.5 10.5

Es fácil ver que cualquier otra operación es aplicable, por ejemplo, la sumatoria, sum():

apply(simplify2array(L), MARGIN=1:2, FUN=sum)
##      [,1] [,2] [,3]
## [1,]   10   22   34
## [2,]   14   26   38
## [3,]   18   30   42

Con esto se concluye la solución del problema.


Si quieres ver este mismo post en mis publicaciones de Rpubs:


Combinar dos vectores en uno, intercalando sus elementos

[Lenguajes: R]

Problema

Dos vectores, de la misma longitud y tipo, se quieren combinar para crear un tercer vector, con los elementos de los originales intercalados.

Esto es algo semejante a lo que se presenta a continuación:

v1 <- c(1,2,3)
v2 <- c(4,5,6)
OPERACION(v1,v2)
## [1] 1 4 2 5 3 6

Solución

Para resolver este problema, recurriremos a la construcción de matrices a partir de sus renglones con la función rbind().

Recordemos también que, en R, las matrices se guardan como una secuencia de sus columnas, así que la simple conversión de la matriz a un vector numérico nos dará el resultado deseado, como se muestra a continuación.

v3 <- as.numeric(rbind(v1, v2))
v3
## [1] 1 4 2 5 3 6

Aquí concluye la solución.


Si quieres ver este mismo post en mis publicaciones de Rpubs:


Manipulación de los nombres de las funciones 1

[Lenguajes: R]

Problema

En R las funciones se guardan en variables, por ejemplo, una función que simplemente imprima su argumento podría darse por
miFun <- function(x) {print(x)}
# La ejecutamos así
miFun("cualquier cosa")
## [1] "cualquier cosa"
Puede ocurrir, sin embargo, que el nombre de la función esté contenida, como un string de caracteres, en otra variable:
nombreF <- "miFun"
Supongamos que no se tiene acceso a la variable miFun, sino únicamente a la variable nombreF. ¿De qué manera se podría ejecutar la función a partir de eso? Esto es, tener algo como:
EJECUTA(nombreF)("algún argumento")
## [1] "algún argumento"

Solución

Para resolver este problema, recurriremos a dos funciones primitivas del lenguaje, assign() y get(), que permiten asignar variables, y extraer valores de variables a partir de sus nombres dados como strings de caracteres:
# La asignación 
x <- 3
# Es lo mismo que:
assign("x", 3)
# La extracción de un valor:
x
## [1] 3
# Es lo mismo que
get("x")
## [1] 3
Por otra parte, la sintaxis de este lenguaje permite ejecutar una función a partir de la variable que ha servido para definirla, o a partir del nombre de la variable dada como un string de caracteres constante. Así,
miFun("cualquier cosa")
## [1] "cualquier cosa"
tiene el mismo resultado que:
"miFun"("cualquier cosa") # NOTE las comillas en el nombre de la función
## [1] "cualquier cosa"
Combinando todo esto, llegamos al resultado deseado de ejecutar la función a partir de una variable que contiene su nombre (nombreF), de la siguiente manera:
get(nombreF)("cualquier cosa") 
## [1] "cualquier cosa"

Si quieres ver este mismo post en mis publicaciones de Rpubs:

miércoles, 8 de julio de 2015

Crear un factor de R, a partir de enteros

[Lenguajes: R]

Problema

En R, los factores son como vectores que aceptan valores descriptivos. Por ejemplo, en algún tipo de experimento se pudiera caracterizar el nivel de energía de una batería, con cuatro niveles: vacio, bajo, normal, lleno. Entonces, para 5 sitios o experimentos diferentes, se podrían identificar esos niveles, en esos términos, como sigue:

lleno, lleno, normal, vacio, bajo

Normalmente, en bases de datos o en otras fuentes de información, el manejo típico de estos datos es mediante índices enteros arbitrarios asociados con las categorías o niveles, en este caso. Si suponemos que se asignaran, para el caso del ejemplo, en orden, como sigue: 1=vacio, 2=bajo, 3=normal, 4=lleno, entonces, los 5 experimentos podrían codificarse así:

4, 4, 3, 1, 2

Sucede, muchas veces, que se cuenta con la lista codificada de enteros, y con la tabla o catálogo de los índices, pero no con el factor ya construído. ¿Cómo se puede reconstruir, entonces, un factor de R, a partir de esa información?

Solución

Para resolver este problema simularemos una vector de 20 enteros que represente los experimentos, cada uno de los cuales podrá tener cinco diferentes valores: nivelUno, nivelDos, nivelTres, nivelCuatro, nivelCinco.

# Hagamos la lista simulada:
set.seed(18)
ii <- sample(1:5, 20, replace=T)
ii
##  [1] 5 4 5 1 1 3 2 3 2 2 4 4 1 2 5 1 3 1 5 1

El primer paso consiste en hacer un factor, a partir de la secuencia previa, en el que los niveles o categorías sean exactamente los números del 1 al 5.

fii <- factor(ii, levels=1:5) # necesario indicar los niveles numericos
fii
##  [1] 5 4 5 1 1 3 2 3 2 2 4 4 1 2 5 1 3 1 5 1
## Levels: 1 2 3 4 5

Ahora simplemente, hay que vestir el factor ya creado con las etiquetas correspondientes a los índices:

levels(fii) <- c("nivelUno", "nivelDos", "nivelTres", "nivelCuatro", "nivelCinco")
fii
##  [1] nivelCinco  nivelCuatro nivelCinco  nivelUno    nivelUno   
##  [6] nivelTres   nivelDos    nivelTres   nivelDos    nivelDos   
## [11] nivelCuatro nivelCuatro nivelUno    nivelDos    nivelCinco 
## [16] nivelUno    nivelTres   nivelUno    nivelCinco  nivelUno   
## Levels: nivelUno nivelDos nivelTres nivelCuatro nivelCinco

Con esto se concluye el ejemplo.


Si quieres ver este mismo post en mis publicaciones de Rpubs:


martes, 7 de julio de 2015

Funciones acumulativas 1

[Lenguajes: R]

Problema

En R hay varias funciones acumulativas, que operan sobre un vector de datos. Por ejemplo, la función sum(), hace la sumatoria de los números contenidos en el vector que se le pasa como argumento:

sum(c(8,-2,5))
## [1] 11

Otro ejemplo es la función prod(), que, de manera similar a la anterior, hace el producto.

La pregunta que surge es: ¿Hay una función que permita hacer lo mismo, pero para un operador, o función, arbitraria?

Solución

La respuesta a la pregunta anterior es , y el nombre de dicha función es Reduce(), que toma al menos los siguientes argumentos:

  • el operador o función que se aplica
  • el vector de datos

Por ejemplo, para hacer una sumatoria como la del ejemplo anterior, con Reduce() se haría así:

Reduce('+', c(8,-2,5)) # Nótese que el operador va con ''
## [1] 11

Para cualquier otro operador, digamos la división:

Reduce('/', c(8,-2,5)) # Nótese que el operador va con ''
## [1] -0.8

Lo interesante de esta función es que admite, como primer argumento, cualquier función de dos argumentos, particularmente, las que nosotros mismos pudieramos escribir o crear.

Por ejemplo:

# Sea 'ff' una función que multiplica por 2 el primer argumento y
# ese resultado lo divide por el segundo argumento:
ff <- function (x, y) {
    2*x / y
}
# Apliquemos secuencialmente esta función a los elementos de
# un vector
Reduce(ff, c(8,-2,5)) # Reduce admite ff, y también 'ff'
## [1] -3.2

Una característica interesante de Reduce(), es que mediante su argumento, opcional, accumulate, se le puede indicar que entregue cada uno de los resultados intermedios de la operación. Para ejemplificar esto, supóngase que se cuenta en un vector con las alturas individuales de cada uno de los pisos de un edificio y que se quiere saber, desde el suelo, cuál es la altura total de cada uno de los niveles del edificio. El problema se resuelve fácilmente así:

# Vector de alturas de los pisos individuales:
alturas <- c(3.10, 3.15, 3.05, 2.95, 3.10, 3.20)
# Niveles, desde el suelo
niveles <- Reduce('+', alturas, accumulate = TRUE)
niveles
## [1]  3.10  6.25  9.30 12.25 15.35 18.55

Si quieres ver este mismo post en mis publicaciones de Rpubs: