2012-10-10 22 views
6

Mirando a través de la función de ave, he encontrado una línea notable:asignación al resultado de una función de cambios de variables

split(x, g) <- lapply(split(x, g), FUN) # From ave 

Curiosamente, esta línea cambia el valor de x, que encontré inesperado. Esperaba que split(x,g) daría como resultado una lista, que podría asignarse, pero descartarse después. Mi pregunta es, ¿por qué cambia el valor de x?

Otro ejemplo puede explicar mejor:

a <- data.frame(id=c(1,1,2,2), value=c(4,5,7,6)) 
# id value 
# 1 1  4 
# 2 1  5 
# 3 2  7 
# 4 2  6 

split(a,a$id) # Split a row-wise by id into a list of size 2 
# $`1` 
# id value 
# 1 1  4 
# 2 1  5 
# $`2` 
# id value 
# 3 2  7 
# 4 2  6 

# Find the row with highest value for each id 
lapply(split(a,a$id),function(x) x[which.max(x$value),]) 
# $`1` 
# id value 
# 2 1  5 
# $`2` 
# id value 
# 3 2  7 

# Assigning to the split changes the data.frame a! 
split(a,a$id)<-lapply(split(a,a$id),function(x) x[which.max(x$value),]) 
a 
# id value 
# 1 1  5 
# 2 1  5 
# 3 2  7 
# 4 2  7 

no sólo ha cambiado a, pero cambiado a un valor que no se ve como el lado derecho de la asignación! Incluso si la asignación a split(a,a$id) cambia de alguna manera a (que no entiendo), ¿por qué resulta en data.frame en lugar de list?

Tenga en cuenta que entiendo que hay mejores formas de llevar a cabo esta tarea. Mi pregunta es ¿por qué split(a,a$id)<-lapply(split(a,a$id),function(x) x[which.max(x$value),]) cambia a?

+2

La función a la que llamas es 'split <-', no' split'. Son dos funciones diferentes. Mire 'split <-. Default 'y es obvio por qué' a' cambia. –

+0

Y debe usar las comillas inversas para imprimir la función porque el nombre de la función contiene un operador: '\' split <-. Default \ ''. –

+0

En este caso, ¿la función relevante no sería '\' split <-. Data.frame \ ''? – nograpes

Respuesta

2

La página de ayuda para dividir dice en su encabezado: "Las formas de reemplazo reemplazar los valores correspondientes a esta división. " Entonces, realmente no debería ser inesperado, aunque admito que no se usa ampliamente. No entiendo cómo su ejemplo ilustra que los valores asignados "¡no se parecen al RHS de la asignación!". Los valores máximos se asignan a las listas de 'valores' dentro de las categorías definidas por el segundo factor de argumento.

(te des las gracias por la pregunta. No me había dado cuenta de que split<- era el núcleo de ave. Creo que es más ampliamente utilizado de lo que pensaba, ya que creo ave es una función maravillosamente útil.)

+0

Ya veo. Mi problema era que no me daba cuenta de que 'split <-' era en sí mismo una función. Sospecho que esta función se puede usar para un código muy inteligente, conciso y eficiente. Gracias por tu respuesta. – nograpes

+0

Tipo: métodos (\ 'split <- \') –

1

Justo después definición de a, realice split(a, a$id)=1, el resultado sería:

> a 
    id value 
1 1  1 
2 1  1 
3 1  1 
4 1  1 
+1

'split' no devuelve los resultados por referencia. –

+0

@DWin Gracias Corregí mi respuesta – Ali

0

La clave aquí es esa fracción de < - en realidad modificado el LHS con valores de derecha.

He aquí un ejemplo:

> x <- c(1,2,3); 
> split(x,x==2) 
$`FALSE` 
[1] 1 3 
$`TRUE` 
[1] 2 
> split(x,x==2) <- split(c(10,20,30),c(10,20,30)==20) 
> x 
[1] 10 20 30 

Nota de la línea en la que volver a asignar split(x,x==2) <-. Esto realmente reasigna x.

Como los comentarios a continuación han declarado, se puede buscar la definición de split<- al igual que

> `split<-.default` 
function (x, f, drop = FALSE, ..., value) 
{ 
    ix <- split(seq_along(x), f, drop = drop, ...) 
    n <- length(value) 
    j <- 0 
    for (i in ix) { 
     j <- j%%n + 1 
     x[i] <- value[[j]] 
    } 
    x 
} 
<bytecode: 0x1e18ef8> 
<environment: namespace:base> 
+2

'split <-' es lo que se está llamando y está escrito en R. –

+0

¿Cómo mostraría el código para eso?Al menos para split, puedo simplemente teclear "split" y da como resultado: función (x, f, drop = FALSE, ...) UseMethod ("split") Arcymag

+0

Y para agregar a lo que dice Joshua dividir (en el RHS) _desea_ valores devueltos, y NO pasa por referencia. –

Cuestiones relacionadas