¿Cómo entender qué contenido se puede poner dentro o fuera de las llaves?

Chris:

Como un principiante de R, he estado luchando con la lectura de código complicado (al menos para mí, es complicado). Cuando leí código simple, la estructura es muy clara. Les puedo decir que son argumentos, que son variables y algo más así como así. Me gusta:

x <- c(1, 2, 3)

Pero cuando leo algo de código complicado, me confundo. Por ejemplo:

output <- vector("double", ncol(df))  
for (i in seq_along(df)) {            
  output[[i]] <- median(df[[i]]) 
}
output

No sé qué es "en" antes seq_along (DF) no otros (utilizo? Seq_along pero no hay respuesta). No sé por qué "(i en seq_along (df))" no está en las llaves. ¿Es una condición o? si hay una lógica básica en la programación de la lengua a través del cual puedo decir lo que se puede poner donde? Cómo leer el código complicado en R, quiero decir que si hay alguna lógica que puedo seguir?

Sólo Greško:

La estructura básica de una for()función en R es:

for(condition that iterates) {
   # do something
}

El operador de llaves {y }toma todo lo que sucedió en la función anterior for()y lo aplica a las sentencias de programación dentro de las llaves.

El [[plazo de su pregunta es una de las cuatro formas del operador extracto . [[específicamente le permite a uno para extraer un elemento de una lista mientras que el apoyo un índice calculado. Me dan ejemplos de tres de las formas del operador extracto en mi artículo, las formas del extracto del operador . La cuarta forma, @(también conocido como el operador de la ranura) es única para objetos construidos con el sistema objeto S4 en R, y no se usa típicamente por los programadores principiantes R.

En cuanto a aprender a leer código R, la referencia que he publicado en los comentarios, R Programación por Roger Peng, es un recurso razonable "libre" ya que se puede optar por pagar $ 0 para él.

Explicación de código en el post original

Aquí vamos a caminar a través del ejemplo original y explicar lo que está pasando. Dado que dfno estaba definido en el post original, vamos a utilizar la mtcarstrama de datos.

df <- mtcars

# instantiate a vector object with length equal to number of columns in 
# df, which in this example should be 11
output <- vector("double",ncol(df)) 
length(output)

> length(output)
[1] 11
> 

En este punto hemos definido un vector de salida con una longitud de 11, que coincide con el número de columnas en df.

A continuación, la for()función establece el valor de ilos números secuenciales únicas entre 1 y el número de columnas df.

Podemos ver esto imprimiendo el resultado de seq_along().

# illustrate what seq_along() does
seq_along(df)
> seq_along(df)
 [1]  1  2  3  4  5  6  7  8  9 10 11
> 

Para cada valor de i, calcula la mediana de la columna asociada en dfy lo guarda en el elemento correspondiente dentro output.

# iterate across columns in df, from 1:11 
for (i in seq_along(df)){
     output[[i]] <- median(df[[i]])
}

R soporta la asignación de nombres a los elementos de un vector. Para que sea evidente lo que sucedió en el for()bucle, vamos a establecer los nombres de los elementos en outputque los nombres de columna df, e imprimir el vector.

# add names to output vector and print 
names(output) <- colnames(df)
output



> output
    mpg     cyl    disp      hp    drat      wt    qsec      vs      am    gear    carb 
 19.200   6.000 196.300 123.000   3.695   3.325  17.710   0.000   0.000   4.000   2.000 
> 

Importancia del [[operador extracto

En este punto comienza un usuario R podría preguntar, "¿Por qué hace esto utilice el código de la [[forma del extracto de operador en lugar de [?"

La clave es que para el código en la pregunta original, el [formulario devuelve un objeto de tipo data.frame(), mientras [[evalúa la trama de datos y devuelve un vector numérico. Podemos ilustrar esto con la str()función, que devuelve la estructura de un objeto R.

str(df[1]) # returns a data frame
str(df[[1]]) # returns a numeric vector

> str(df[1]) # returns a data frame
'data.frame':   32 obs. of  1 variable:
 $ mpg: num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
> str(df[[1]]) # returns a numeric vector
 num [1:32] 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
>

La median()función espera un vector numérico como entrada. Pasándolo a una trama de datos en lugar de un vector genera error "necesidad de datos numéricos".

> median(df[1])
Error in median.default(df[1]) : need numeric data
> 

Otra forma de explicar lo que R está haciendo en esta situación es que los df[1]subconjuntos de una trama de datos para devolver una trama de datos con una sola columna, mientras que df[[1]]no sólo subconjuntos de la trama de datos a una sola columna, sino también subconjuntos de forma recursiva a devolver los valores de la primera columna como un vector. Por subconjuntos de más de 2 columnas, podemos hacer que el subconjunto recursiva falle.

# illustrate recursive subsetting with a case that will fail
head(df[1:3]) # print 6 rows of first 3 columns
head(df[[1:3]]) # fails with recursive subset error

> head(df[1:3]) # print 6 rows of first 3 columns
                   mpg cyl disp
Mazda RX4         21.0   6  160
Mazda RX4 Wag     21.0   6  160
Datsun 710        22.8   4  108
Hornet 4 Drive    21.4   6  258
Hornet Sportabout 18.7   8  360
Valiant           18.1   6  225
> head(df[[1:3]]) # fails with recursive subset error
Error in .subset2(x, i, exact = exact) : 
  recursive indexing failed at level 2
>

Muchas maneras de resolver un problema en I

Una vez explicado el código en la pregunta original, es importante tener en cuenta que hay muchas maneras de hacer algo en R. Aquí vamos a utilizar una versión de for()que itera sobre la base de los nombres de columna df, y usa la [[forma del operador de extracción para extraer en la columna correcta dfpara calcular la mediana.

# now illustrate same code by iterating over column names
output2 <- vector("double",ncol(df)) 
names(output2) <- colnames(df)
columnNames <- colnames(df)
for (i in columnNames){
     output2[[i]] <- median(df[[i]])
}
output2
> output2
    mpg     cyl    disp      hp    drat      wt    qsec      vs      am    gear    carb 
 19.200   6.000 196.300 123.000   3.695   3.325  17.710   0.000   0.000   4.000   2.000 
>

Una sutileza importante en esta solución es que mediante la asignación de nombres a los elementos en output2que podemos utilizar los nombres para indexar el vector de salida, así como la trama de datos de entrada. De hecho, si no hubiéramos asignado los nombres del bucle produciría resultados inexactos, añadiendo los valores con nombre en elementos de 12:22 en el vector.

Por último, a medida que avanza en el aprendizaje de R, usted aprenderá acerca de la apply()familia de funciones, que permiten a uno para evitar for()bucles. Una solución para el mismo problema utilizando lapply()o "aplica lista" se ilustra el siguiente bloque de código. El bloque de código también implementa una función anónima , que es como cualquier otra función R, excepto que no se le da un nombre. Dado que lapply()devuelve una lista y sabemos que cada elemento de la lista es un número único, se utiliza unlist()para convertir la lista devuelta por lapply()en un vector.

# produce same output with a different technique: lapply()
columnNames <- colnames(df)
output3 <- unlist(lapply(columnNames,function(x){
     median(df[[x]])
}))
names(output3) <- colnames(df)
output3
> output3
    mpg     cyl    disp      hp    drat      wt    qsec      vs      am    gear    carb 
 19.200   6.000 196.300 123.000   3.695   3.325  17.710   0.000   0.000   4.000   2.000 
> 

Supongo que te gusta

Origin http://10.200.1.11:23101/article/api/json?id=406616&siteId=1
Recomendado
Clasificación