ggplot - ¿Cuál es el truco R más útil?
r plot legend (30)
Para compartir más consejos y trucos para R , ¿cuál es tu característica o truco más útil? ¿Vectorización inteligente? Entrada / salida de datos? Visualización y gráficos? ¿Análisis estadístico? ¿Funciones especiales? El entorno interactivo en sí?
Un artículo por publicación, y veremos si obtenemos un ganador por medio de los votos.
[Editar 25-ago 2008]: Entonces, después de una semana, parece que el simple str()
ganó la encuesta. Como me gustaría recomendarlo yo mismo, es una respuesta fácil de aceptar.
Truco de entrada de datos = paquete RGoogleDocs
http://www.omegahat.org/RGoogleDocs/
He encontrado que las hojas de cálculo de Google son una manera fantástica para que todos los colaboradores estén en sintonía. Además, Google Forms permite capturar datos de los encuestados y escribirlos sin esfuerzo en una hoja de cálculo de Google. Debido a que los datos cambian con frecuencia y casi nunca son definitivos, es preferible que R lea una hoja de cálculo de Google directamente que con la descarga de archivos csv y su lectura.
# Get data from google spreadsheet
library(RGoogleDocs)
ps <-readline(prompt="get the password in ")
auth = getGoogleAuth("[email protected]", ps, service="wise")
sheets.con <- getGoogleDocsConnection(auth)
ts2=getWorksheets("Data Collection Repos",sheets.con)
names(ts2)
init.consent <-sheetAsMatrix(ts2$Sheet1,header=TRUE, as.data.frame=TRUE, trim=TRUE)
No puedo recordar cuál, pero uno o dos de los siguientes comandos toman varios segundos.
getGoogleAuth
getGoogleDocsConnection
getWorksheets
Algunas veces necesita rbind
múltiples marcos de datos. do.call()
te dejará hacer eso (alguien tuvo que explicarme esto cuando bind formulé esta pregunta, ya que no parece ser un uso obvio).
foo <- list()
foo[[1]] <- data.frame(a=1:5, b=11:15)
foo[[2]] <- data.frame(a=101:105, b=111:115)
foo[[3]] <- data.frame(a=200:210, b=300:310)
do.call(rbind, foo)
Aquí hay una solución molesta para convertir un factor en numérico. (Similar para otros tipos de datos también)
old.var <- as.numeric(levels(old.var))[as.numeric(old.var)]
Aunque esta pregunta ha estado por un tiempo, recientemente descubrí un gran truco en el blog SAS y R para usar el comando de cut
. El comando se usa para dividir datos en categorías y usaré el conjunto de datos del iris como un ejemplo y lo dividiré en 10 categorías:
> irisSL <- iris$Sepal.Length
> str(irisSL)
num [1:150] 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
> cut(irisSL, 10)
[1] (5.02,5.38] (4.66,5.02] (4.66,5.02] (4.3,4.66] (4.66,5.02] (5.38,5.74] (4.3,4.66] (4.66,5.02] (4.3,4.66] (4.66,5.02]
[11] (5.38,5.74] (4.66,5.02] (4.66,5.02] (4.3,4.66] (5.74,6.1] (5.38,5.74] (5.38,5.74] (5.02,5.38] (5.38,5.74] (5.02,5.38]
[21] (5.38,5.74] (5.02,5.38] (4.3,4.66] (5.02,5.38] (4.66,5.02] (4.66,5.02] (4.66,5.02] (5.02,5.38] (5.02,5.38] (4.66,5.02]
[31] (4.66,5.02] (5.38,5.74] (5.02,5.38] (5.38,5.74] (4.66,5.02] (4.66,5.02] (5.38,5.74] (4.66,5.02] (4.3,4.66] (5.02,5.38]
[41] (4.66,5.02] (4.3,4.66] (4.3,4.66] (4.66,5.02] (5.02,5.38] (4.66,5.02] (5.02,5.38] (4.3,4.66] (5.02,5.38] (4.66,5.02]
[51] (6.82,7.18] (6.1,6.46] (6.82,7.18] (5.38,5.74] (6.46,6.82] (5.38,5.74] (6.1,6.46] (4.66,5.02] (6.46,6.82] (5.02,5.38]
[61] (4.66,5.02] (5.74,6.1] (5.74,6.1] (5.74,6.1] (5.38,5.74] (6.46,6.82] (5.38,5.74] (5.74,6.1] (6.1,6.46] (5.38,5.74]
[71] (5.74,6.1] (5.74,6.1] (6.1,6.46] (5.74,6.1] (6.1,6.46] (6.46,6.82] (6.46,6.82] (6.46,6.82] (5.74,6.1] (5.38,5.74]
[81] (5.38,5.74] (5.38,5.74] (5.74,6.1] (5.74,6.1] (5.38,5.74] (5.74,6.1] (6.46,6.82] (6.1,6.46] (5.38,5.74] (5.38,5.74]
[91] (5.38,5.74] (5.74,6.1] (5.74,6.1] (4.66,5.02] (5.38,5.74] (5.38,5.74] (5.38,5.74] (6.1,6.46] (5.02,5.38] (5.38,5.74]
[101] (6.1,6.46] (5.74,6.1] (6.82,7.18] (6.1,6.46] (6.46,6.82] (7.54,7.9] (4.66,5.02] (7.18,7.54] (6.46,6.82] (7.18,7.54]
[111] (6.46,6.82] (6.1,6.46] (6.46,6.82] (5.38,5.74] (5.74,6.1] (6.1,6.46] (6.46,6.82] (7.54,7.9] (7.54,7.9] (5.74,6.1]
[121] (6.82,7.18] (5.38,5.74] (7.54,7.9] (6.1,6.46] (6.46,6.82] (7.18,7.54] (6.1,6.46] (5.74,6.1] (6.1,6.46] (7.18,7.54]
[131] (7.18,7.54] (7.54,7.9] (6.1,6.46] (6.1,6.46] (5.74,6.1] (7.54,7.9] (6.1,6.46] (6.1,6.46] (5.74,6.1] (6.82,7.18]
[141] (6.46,6.82] (6.82,7.18] (5.74,6.1] (6.46,6.82] (6.46,6.82] (6.46,6.82] (6.1,6.46] (6.46,6.82] (6.1,6.46] (5.74,6.1]
10 Levels: (4.3,4.66] (4.66,5.02] (5.02,5.38] (5.38,5.74] (5.74,6.1] (6.1,6.46] (6.46,6.82] (6.82,7.18] ... (7.54,7.9]
Como un novato total para R y un novato en las estadísticas, me encanta unclass()
para imprimir todos los elementos de un marco de datos como una lista ordinaria.
Es muy útil para echar un vistazo a un conjunto completo de datos, todo en uno, para analizar rápidamente cualquier posible problema.
Definitivamente system()
. Poder acceder a todas las herramientas de Unix (al menos en Linux / MacOSX) desde dentro del entorno R se ha convertido rápidamente en un valor incalculable en mi flujo de trabajo diario.
En la programación R (no en las sesiones interactivas), uso if (bad.condition) stop("message")
mucho . Cada función comienza con algunas de estas y, a medida que trabajo en los cálculos, también las realizo. Supongo que adquirí el hábito de usar assert()
en C. Los beneficios son dobles. En primer lugar, es mucho más rápido obtener código de trabajo con estos controles en su lugar. En segundo lugar, y probablemente más importante, es mucho más fácil trabajar con el código existente cuando ve estas comprobaciones en cada pantalla de su editor. No tendrá que preguntarse si x>0
, o confiar en un comentario que indique que es ... sabrá , de un vistazo, que sí lo es.
PD. mi primera publicación aquí. ¡Sé gentil!
Estoy realmente sorprendido de que nadie haya publicado sobre aplicar, aplicar, aplicar y aplicar. Una regla general que uso cuando hago cosas en R es que si tengo un bucle for que está haciendo procesamiento de datos o simulaciones, trato de factorizarlo y reemplazarlo con * apply. Algunas personas evitan las funciones * apply porque creen que solo se pueden pasar funciones de un solo parámetro. ¡Nada podría estar más lejos de la verdad! Como pasar funciones con parámetros como objetos de primera clase en Javascript, haz esto en R con funciones anónimas. Por ejemplo:
> sapply(rnorm(100, 0, 1), round)
[1] 1 1 0 1 1 -1 -2 0 2 2 -2 -1 0 1 -1 0 1 -1 0 -1 0 0 0 0 0
[26] 2 0 -1 -2 0 0 1 -1 1 5 1 -1 0 1 1 1 2 0 -1 1 -1 1 0 -1 1
[51] 2 1 1 -2 -1 0 -1 2 -1 1 -1 1 -1 0 -1 -2 1 1 0 -1 -1 1 1 2 0
[76] 0 0 0 -2 -1 1 1 -2 1 -1 1 1 1 0 0 0 -1 -3 0 -1 0 0 0 1 1
> sapply(rnorm(100, 0, 1), round(x, 2)) # How can we pass a parameter?
Error in match.fun(FUN) : object ''x'' not found
# Wrap your function call in an anonymous function to use parameters
> sapply(rnorm(100, 0, 1), function(x) {round(x, 2)})
[1] -0.05 -1.74 -0.09 -1.23 0.69 -1.43 0.76 0.55 0.96 -0.47 -0.81 -0.47
[13] 0.27 0.32 0.47 -1.28 -1.44 -1.93 0.51 -0.82 -0.06 -1.41 1.23 -0.26
[25] 0.22 -0.04 -2.17 0.60 -0.10 -0.92 0.13 2.62 1.03 -1.33 -1.73 -0.08
[37] 0.45 -0.93 0.40 0.05 1.09 -1.23 -0.35 0.62 0.01 -1.08 1.70 -1.27
[49] 0.55 0.60 -1.46 1.08 -1.88 -0.15 0.21 0.06 0.53 -1.16 -2.13 -0.03
[61] 0.33 -1.07 0.98 0.62 -0.01 -0.53 -1.17 -0.28 -0.95 0.71 -0.58 -0.03
[73] -1.47 -0.75 -0.54 0.42 -1.63 0.05 -1.90 0.40 -0.01 0.14 -1.58 1.37
[85] -1.00 -0.90 1.69 -0.11 -2.19 -0.74 1.34 -0.75 -0.51 -0.99 -0.36 -1.63
[97] -0.98 0.61 1.01 0.55
# Note that anonymous functions aren''t being called, but being passed.
> function() {print(''hello #rstats'')}()
function() {print(''hello #rstats'')}()
> a = function() {print(''hello #rstats'')}
> a
function() {print(''hello #rstats'')}
> a()
[1] "hello #rstats"
(Para aquellos que siguen #rstats, también publiqué esto allí).
Recuerde, use apply, sapply, lapply, tapply y do.call! Aproveche la vectorización de R. Nunca debe acercarse a un montón de código R y ver:
N = 10000
l = numeric()
for (i in seq(1:N)) {
sim <- rnorm(1, 0, 1)
l <- rbind(l, sim)
}
No solo esto no está vectorizado, sino que la estructura de matriz en R no se cultiva como en Python (duplicando el tamaño cuando se agota el espacio, IIRC). Por lo tanto, cada paso de enlace primero debe crecer lo suficiente como para aceptar los resultados de rbind () y luego copiar todo el contenido de la anterior. Para divertirse, pruebe lo anterior en R. Observe cuánto tiempo lleva (ni siquiera necesitará Rprof ni ninguna función de temporización). Entonces intenta
N=10000
l <- rnorm(N, 0, 1)
Lo siguiente es mejor que la primera versión también:
N = 10000
l = numeric(N)
for (i in seq(1:N)) {
sim <- rnorm(1, 0, 1)
l[i] <- sim
}
Hago mucha manipulación básica de datos, así que aquí hay dos funciones integradas ( transformación , subconjunto ) y una biblioteca ( sqldf ) que uso diariamente.
crear datos de ventas de muestra
sales <- expand.grid(country = c(''USA'', ''UK'', ''FR''),
product = c(1, 2, 3))
sales$revenue <- rnorm(dim(sales)[1], mean=100, sd=10)
> sales
country product revenue
1 USA 1 108.45965
2 UK 1 97.07981
3 FR 1 99.66225
4 USA 2 100.34754
5 UK 2 87.12262
6 FR 2 112.86084
7 USA 3 95.87880
8 UK 3 96.43581
9 FR 3 94.59259
use transform () para agregar una columna
## transform currency to euros
usd2eur <- 1.434
transform(sales, euro = revenue * usd2eur)
>
country product revenue euro
1 USA 1 108.45965 155.5311
2 UK 1 97.07981 139.2125
3 FR 1 99.66225 142.9157
...
usar subconjunto () para cortar los datos
subset(sales,
country == ''USA'' & product %in% c(1, 2),
select = c(''product'', ''revenue''))
>
product revenue
1 1 108.4597
4 2 100.3475
use sqldf () para cortar y agregar con SQL
El paquete sqldf proporciona una interfaz SQL para los marcos de datos R
## recast the previous subset() expression in SQL
sqldf(''SELECT product, revenue FROM sales /
WHERE country = "USA" /
AND product IN (1,2)'')
>
product revenue
1 1 108.4597
2 2 100.3475
Realice una agregación o GROUP BY
sqldf(''select country, sum(revenue) revenue /
FROM sales /
GROUP BY country'')
>
country revenue
1 FR 307.1157
2 UK 280.6382
3 USA 304.6860
Para una funcionalidad más sofisticada de map-reduce-like en marcos de datos, consulte el paquete plyr . Y si te encuentras con deseos de arrancarte el pelo, te recomiendo que revises Data Manipulation con R.
La función traceback()
es imprescindible cuando tienes un error en alguna parte y no lo entiendes fácilmente. Imprimirá un rastro de la pila, muy útil ya que R no es muy detallado por defecto.
Luego, las options(error=recover)
configuración options(error=recover)
le permitirán "ingresar" en la función que genera el error e intentar comprender lo que sucede exactamente, como si tuviera control total sobre ella y pudiera poner un browser()
en ella.
Estas tres funciones realmente pueden ayudar a depurar su código.
Me parece que estoy usando with()
y within()
más y más. No más $
ensuciar mi código y no es necesario comenzar a adjuntar objetos a la ruta de búsqueda. Más en serio, me parece que with()
etc hacen que la intención de mis scripts de análisis de datos sea mucho más clara.
> df <- data.frame(A = runif(10), B = rnorm(10))
> A <- 1:10 ## something else hanging around...
> with(df, A + B) ## I know this will use A in df!
[1] 0.04334784 -0.40444686 1.99368816 0.13871605 -1.17734837
[6] 0.42473812 2.33014226 1.61690799 1.41901860 0.8699079
with()
configura un entorno dentro del cual se evalúa la expresión R. within()
hace lo mismo pero le permite modificar el objeto de datos utilizado para crear el entorno.
> df <- within(df, C <- rpois(10, lambda = 2))
> head(df)
A B C
1 0.62635571 -0.5830079 1
2 0.04810539 -0.4525522 1
3 0.39706979 1.5966184 3
4 0.95802501 -0.8193090 2
5 0.76772541 -1.9450738 2
6 0.21335006 0.2113881 4
Algo de lo que no me di cuenta cuando lo utilicé por primera vez within()
es que debe hacer una tarea como parte de la expresión evaluada y asignar el objeto devuelto (como se indicó anteriormente) para obtener el efecto deseado.
Mi nueva cosa favorita es la biblioteca foreach. Te permite hacer todas las aplicaciones agradables, pero con una sintaxis algo más fácil:
list_powers <- foreach(i = 1:100) %do% {
lp <- x[i]^i
return (lp)
}
La mejor parte es que si está haciendo algo que realmente requiere una cantidad de tiempo considerable, puede cambiar de %do%
a %dopar%
(con la biblioteca de fondo adecuada) para paralelizar instantáneamente, incluso a través de un clúster. Muy resbaladizo
No sé qué tan conocido es / no es esto, pero algo de lo que definitivamente me he aprovechado son las capacidades de paso de referencia de los entornos.
zz <- new.env()
zz$foo <- c(1,2,3,4,5)
changer <- function(blah) {
blah$foo <- 5
}
changer(zz)
zz$foo
Para este ejemplo, no tiene sentido por qué sería útil, pero si pasas objetos grandes alrededor puede ser útil.
Otro truco Algunos paquetes, como glmnet, solo toman como entradas la matriz de diseño y la variable de respuesta. Si uno quiere ajustar un modelo con todas las interacciones entre características, no puede usar la fórmula "y ~. ^ 2". El uso de expand.grid()
nos permite aprovechar la potente indexación de matrices y las operaciones vectoriales de R.
interArray=function(X){
n=ncol(X)
ind=expand.grid(1:n,1:n)
return(X[,ind[,1]]*X[,ind[,2]])
}
> X
X1 X2
1 0.96852363 0.33827107
2 0.08012755 0.69159828
3 0.10167545 0.38119304
4 0.06699458 0.41756415
5 0.08187816 0.09805104
> interArray(X)
X1 X2 X1.1 X2.1
1 0.938038022 0.327623524 0.327623524 0.114427316
2 0.006420424 0.055416073 0.055416073 0.478308177
3 0.010337897 0.038757974 0.038757974 0.145308137
4 0.004488274 0.027974536 0.027974536 0.174359821
5 0.006704033 0.008028239 0.008028239 0.009614007
Puede asignar un valor que retorna desde un bloque if-else.
En lugar de, por ejemplo
condition <- runif(1) > 0.5
if(condition) x <- 1 else x <- 2
tu puedes hacer
x <- if(condition) 1 else 2
Exactamente cómo funciona esto es magia profunda.
Sobre el consejo de Dirk, estoy publicando ejemplos individuales. Espero que no sean demasiado "lindos" [inteligentes, pero no me importa] o triviales para esta audiencia.
Los modelos lineales son el pan y la mantequilla de R. Cuando el número de variables independientes es alto, uno tiene dos opciones. El primero es usar lm.fit (), que recibe la matriz de diseño xy la respuesta y como argumentos, de manera similar a Matlab. El inconveniente de este enfoque es que el valor de retorno es una lista de objetos (coeficientes ajustados, residuales, etc.), no un objeto de la clase "lm", que puede resumirse muy bien, utilizarse para la predicción, la selección por pasos, etc. El segundo enfoque es crear una fórmula:
> A
X1 X2 X3 X4 y
1 0.96852363 0.33827107 0.261332257 0.62817021 1.6425326
2 0.08012755 0.69159828 0.087994158 0.93780481 0.9801304
3 0.10167545 0.38119304 0.865209832 0.16501662 0.4830873
4 0.06699458 0.41756415 0.258071616 0.34027775 0.7508766
...
> (f=paste("y ~",paste(names(A)[1:4],collapse=" + ")))
[1] "y ~ X1 + X2 + X3 + X4"
> lm(formula(f),data=A)
Call:
lm(formula = formula(f), data = A)
Coefficients:
(Intercept) X1 X2 X3 X4
0.78236 0.95406 -0.06738 -0.43686 -0.06644
Una característica interesante: la lectura de datos usa conexiones que pueden ser archivos locales, archivos remotos a los que se accede a través de http, canalizaciones de otros programas o más.
Como un ejemplo simple, considere este acceso para N = 10 enteros aleatorios entre min = 100 y max = 200 de random.org (que proporciona números aleatorios verdaderos basados en el ruido atmosférico en lugar de un generador de números pseudoaleatorios):
R> site <- "http://random.org/integers/" # base URL
R> query <- "num=10&min=100&max=200&col=2&base=10&format=plain&rnd=new"
R> txt <- paste(site, query, sep="?") # concat url and query string
R> nums <- read.table(file=txt) # and read the data
R> nums # and show it
V1 V2
1 165 143
2 107 118
3 103 132
4 191 100
5 138 185
R>
Como un aparte, el paquete random proporciona varias funciones de conveniencia para acceder a random.org .
Una forma de acelerar el código y eliminar los bucles.
en lugar de bucles que recorren un marco de datos en busca de valores. solo tome un subconjunto del df con esos valores, mucho más rápido.
Entonces, en lugar de:
for(i in 1:nrow(df)){
if (df$column[i] == x) {
df$column2[i] <- y
or any other similiar code
}
}
haz algo como esto:
df$column2[df$column1 == x] <- y
ese concepto de base es aplicable con mucha frecuencia y es una excelente manera de deshacerse de los bucles for
Una función muy útil que suelo usar es dput (), que te permite volcar un objeto en forma de código R.
# Use the iris data set
R> data(iris)
# dput of a numeric vector
R> dput(iris$Petal.Length)
c(1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.6,
1.4, 1.1, 1.2, 1.5, 1.3, 1.4, 1.7, 1.5, 1.7, 1.5, 1, 1.7, 1.9,
1.6, 1.6, 1.5, 1.4, 1.6, 1.6, 1.5, 1.5, 1.4, 1.5, 1.2, 1.3, 1.4,
1.3, 1.5, 1.3, 1.3, 1.3, 1.6, 1.9, 1.4, 1.6, 1.4, 1.5, 1.4, 4.7,
4.5, 4.9, 4, 4.6, 4.5, 4.7, 3.3, 4.6, 3.9, 3.5, 4.2, 4, 4.7,
3.6, 4.4, 4.5, 4.1, 4.5, 3.9, 4.8, 4, 4.9, 4.7, 4.3, 4.4, 4.8,
5, 4.5, 3.5, 3.8, 3.7, 3.9, 5.1, 4.5, 4.5, 4.7, 4.4, 4.1, 4,
4.4, 4.6, 4, 3.3, 4.2, 4.2, 4.2, 4.3, 3, 4.1, 6, 5.1, 5.9, 5.6,
5.8, 6.6, 4.5, 6.3, 5.8, 6.1, 5.1, 5.3, 5.5, 5, 5.1, 5.3, 5.5,
6.7, 6.9, 5, 5.7, 4.9, 6.7, 4.9, 5.7, 6, 4.8, 4.9, 5.6, 5.8,
6.1, 6.4, 5.6, 5.1, 5.6, 6.1, 5.6, 5.5, 4.8, 5.4, 5.6, 5.1, 5.1,
5.9, 5.7, 5.2, 5, 5.2, 5.4, 5.1)
# dput of a factor levels
R> dput(levels(iris$Species))
c("setosa", "versicolor", "virginica")
Puede ser muy útil publicar fragmentos de datos fácilmente reproducibles cuando solicite ayuda o para editar o reordenar los niveles de un factor.
Uno de mis trucos preferidos, si no algo heterodoxos, es el uso de eval()
y parse()
. Este ejemplo quizás ilustra cómo puede ser útil
NY.Capital <- ''Albany''
state <- ''NY''
parameter <- ''Capital''
eval(parse(text=paste(state, parameter, sep=''.'')))
[1] "Albany"
Este tipo de situación ocurre más de las veces, y el uso de eval()
y parse()
puede ayudar a resolverlo. Por supuesto, agradezco cualquier comentario sobre formas alternativas de codificar esto.
Use los apoyos para hacer referencia a nombres no estándar.
> df <- data.frame(x=rnorm(5),y=runif(5))
> names(df) <- 1:2
> df
1 2
1 -1.2035003 0.6989573
2 -1.2146266 0.8272276
3 0.3563335 0.0947696
4 -0.4372646 0.9765767
5 -0.9952423 0.6477714
> df$1
Error: unexpected numeric constant in "df$1"
> df$`1`
[1] -1.2035003 -1.2146266 0.3563335 -0.4372646 -0.9952423
En este caso, df [, "1"] también funcionaría. ¡Pero las señales de retroceso funcionan dentro de las fórmulas!
> lm(`2`~`1`,data=df)
Call:
lm(formula = `2` ~ `1`, data = df)
Coefficients:
(Intercept) `1`
0.4087 -0.3440
[Editar] Dirk pregunta por qué uno daría nombres inválidos? ¡No lo sé! Pero ciertamente encuentro este problema en la práctica con bastante frecuencia. Por ejemplo, usando el paquete de remodelación de hadley:
> library(reshape)
> df$z <- c(1,1,2,2,2)
> recast(df,z~.,id.var="z")
Aggregation requires fun.aggregate: length used as default
z (all)
1 1 4
2 2 6
> recast(df,z~.,id.var="z")$(all)
Error: unexpected ''('' in "recast(df,z~.,id.var="z")$("
> recast(df,z~.,id.var="z")$`(all)`
Aggregation requires fun.aggregate: length used as default
[1] 4 6
head () y tail () para obtener la primera y la última parte de un dataframe, vector, matriz, función, etc. Especialmente con grandes marcos de datos, esta es una manera rápida de verificar que se haya cargado correctamente.
CrossTable()
del paquete gmodels
proporciona acceso fácil a tablas cruzadas de estilo SAS y SPSS, junto con las pruebas habituales (Chisq, McNemar, etc.). Básicamente, es xtabs()
con una salida elegante y algunas pruebas adicionales, pero facilita el intercambio de resultados con los paganos.
set.seed()
establece el estado del generador de números aleatorios.
Por ejemplo:
> set.seed(123)
> rnorm(1)
[1] -0.5604756
> rnorm(1)
[1] -0.2301775
> set.seed(123)
> rnorm(1)
[1] -0.5604756
str()
te dice la estructura de cualquier objeto.
For those who are writing C to be called from R: .Internal(inspect(...))
is handy. Por ejemplo:
> .Internal(inspect(quote(a+2)))
@867dc28 06 LANGSXP g0c0 []
@8436998 01 SYMSXP g1c0 [MARK,gp=0x4000] "+"
@85768b0 01 SYMSXP g1c0 [MARK,NAM(2)] "a"
@8d7bf48 14 REALSXP g0c1 [] (len=1, tl=0) 2
To perform an operation on a number of variables in a data frame. This is stolen from subset.data.frame.
get.vars<-function(vars,data){
nl <- as.list(1L:ncol(data))
names(nl) <- names(data)
vars <- eval(substitute(vars), nl, parent.frame())
data[,vars]
#do stuff here
}
get.vars(c(cyl:hwy,class),mpg)
d = ''~/R Code/Library/''
files = list.files(d,''.r$'')
for (f in files) { if (!(f == ''mysource.r'' )) { print(paste(''Sourcing'',f)) source(paste(d,f,sep='''')) } }
I use the above code to source all the files in a directory at start up with various utility programs I use in my interactive session with R. I am sure there are better ways but I find it useful for my work. The line that does this is as follows.
source("~/R Code/Library/mysource.r")
Ya publiqué esto una vez pero lo uso tanto que pensé en publicarlo nuevamente. Es solo una pequeña función para devolver los nombres y los números de posición de un data.frame. No es nada especial para estar seguro, pero casi nunca lo hago a través de una sesión sin usarlo varias veces.
##creates an object from a data.frame listing the column names and location
namesind = function (df) {
temp1=names(df)
temp2=seq(1,length(temp1))
temp3=data.frame(temp1,temp2)
names(temp3)=c("VAR","COL")
return(temp3)
rm(temp1,temp2,temp3)
}
ni <- namesind
?ave
Los subconjuntos de ''x []'' se promedian, donde cada subconjunto consiste en esas observaciones con los mismos niveles de factor. Uso: ave (x, ..., FUN = mean)
Lo uso todo el tiempo. (por ejemplo, en esta respuesta aquí al final )