2012-03-01 14 views
5

Melt and Cast son operaciones populares para manejar datos en R. En F # que serían secuencias de registros del mismo tipo o algo cercano.En F #, ¿hay operaciones como 'derretir' o 'lanzar' en R?

¿Conoce alguna de estas funciones en F #?

(Si no es así, que estaría interesado en hacer alguna versión fuertemente tipado de ellos ...)

Más información:

Melt toma una tabla como entrada. Tiene el título de columna (nuestros campos de registro) y una serie de filas. Los columna se puede agrupar en un conjunto de 'identificador' y un conjunto de 'variables'

Melt pone esta tabla en una nueva forma canónica con las columnas son ahora: los identificadores, la columna denominada @ "variable" , la columna llamada @ "valor"

Si tenía 10 'variables' originalmente, como tamaño, peso, etc. tendrá para cada registro anterior, 10 registros en la forma canónica, con los valores en la columna @ 'variable' se rellena con el título de las columnas anteriores de sus 'variables'

Fundición, a la inversa, reconstruya una tabla de una fundida.

Un breve ejemplo en R, melt toma de datos (dat) que tiene este aspecto:

a   b   c 
1 1 0.48411551 0.2372291 
2 2 0.58850308 0.3968759 
3 3 0.74412592 0.9718320 
4 4 0.93060118 0.8665092 
5 5 0.01556804 0.2512399 

y hace que se vea como esto:

> melt(dat,id.vars = "a") 
    a variable  value 
1 1  b 0.48411551 
2 2  b 0.58850308 
3 3  b 0.74412592 
4 4  b 0.93060118 
5 5  b 0.01556804 
6 1  c 0.23722911 
7 2  c 0.39687586 
8 3  c 0.97183200 
9 4  c 0.86650918 
10 5  c 0.25123992 

cast hace esencialmente lo inverso.

Esas 2 operaciones son extremadamente potentes en el día a día. Una vez que los tienes, cambia tu forma de pensar, al igual que FP.

+3

¿Puedes explicarme qué hacen? – Daniel

+0

Aquí está Melt (no que explica mucho: http://pinard.progiciels-bpi.ca/libR/library/reshape/html/melt-24.html) Cast tiene un poco más de explicación: http: // pinard. progiciels-bpi.ca/libR/library/reshape/html/cast-9g.html. Por supuesto, eso no dice nada sobre lo que @nicolas está buscando. –

+0

O una breve reseña reciente aquí: (http://www.mathfinance.cn/R-reshape-package/) –

Respuesta

2

Suponiendo melt es similar a SQL Server de unpivot, esto debería hacer el truco:

let melt keys (table: DataTable) = 
    let out = new DataTable() 
    let keyCols, otherCols = 
    table.Columns 
    |> Seq.cast<DataColumn> 
    |> Seq.toArray 
    |> Array.partition (fun c -> keys |> Seq.exists (fun k -> k = c.ColumnName)) 
    for c in keyCols do 
    out.Columns.Add(c.ColumnName) |> ignore 
    out.Columns.Add("Key", typeof<string>) |> ignore 
    out.Columns.Add("Value") |> ignore 
    for r in table.Rows do 
    for c in otherCols do 
     let values = [| 
     for c in keyCols do yield r.[c] 
     yield box c.ColumnName 
     yield r.[c] 
     |] 
     out.Rows.Add(values) |> ignore 
    out 

es una pequeña prueba para probarlo aquí:

let table = new DataTable() 
[|"Country", typeof<string> 
    "2001", typeof<int> 
    "2002", typeof<int> 
    "2003", typeof<int>|] 
|> Array.map (fun (name, typ) -> new DataColumn(name, typ)) 
|> table.Columns.AddRange 

[ 
    "Nigeria", 1, 2, 3 
    "UK", 2, 3, 4 
] 
|> List.iter (fun (a, b, c, d) -> table.Rows.Add(a, b, c, d) |> ignore) 

let table2 = table |> melt ["Country"] 

table2.Rows 
|> Seq.cast<DataRow> 
|> Seq.iter (fun r -> 
    for (c: DataColumn) in table2.Columns do 
    printfn "%A: %A" c.ColumnName r.[c] 
    printfn "") 

que produce

"Country": "Nigeria" 
"Key": "2001" 
"Value": "1" 

"Country": "Nigeria" 
"Key": "2002" 
"Value": "2" 

... 

Suponiendo que cast va en la otra dirección (es decir, pivot), debería poder tomar este código y obtener una traducción.

Si está haciendo esto mucho, puede que le resulte más fácil cargar sus datos en SQL Server y usar los operadores incorporados.

+0

Parece que está haciendo lo mismo. A pesar de que estaba esperando (soñando) con un estilo F #, versión seriamente fuertemente tipada. – nicolas

+0

Necesita encabezados de columna para que esto funcione, y como no sé con qué tipos está tratando, utilicé 'DataTable'. Creo que puede tomar la lógica y personalizarla para que funcione con su (s) tipo (s) preferido (s). – Daniel

+0

No veo cómo puedo hacer que el tipo de fusión sea independiente pero fuertemente tipado. ¿tenemos que ir al modo de Proveedor de Tipo? – nicolas

0

¿Conoce alguna de estas funciones en F #?

No hay tales funciones en la biblioteca estándar F #.

Un breve ejemplo en I

Sus datos de ejemplo pueden ser escritos en C# como esto:

let header, data = 
    [ "a"; "b"; "c" ], 
    [ 1, 0.48411551, 0.2372291 
    2, 0.58850308, 0.3968759 
    3, 0.74412592, 0.9718320 
    4, 0.93060118, 0.8665092 
    5, 0.01556804, 0.2512399 ] 

y luego "fundido" de esta manera:

let melt header data = 
    let header, data = Array.ofSeq header, Array.ofSeq data 
    [ header.[0], "variable", "value" ], 
    [ for a, b, c in data do 
     yield a, "b", b 
     yield a, "c", c ] 

Tenga en cuenta que la tipificación estática requiere que sus columnas "b" y "c" contengan valores del mismo tipo porque tienen se ha fusionado en una sola columna.

Esas 2 operaciones son extremadamente potentes en el día a día. Una vez que los tienes, cambia tu forma de pensar, al igual que FP.

No entiendo por qué. Sospecho que este es un problema XY y que está describiendo cómo se pueden resolver los problemas en R cuando el mismo problema sería mejor resuelto usando un enfoque más tipo en F # como un mapa de "a" a un mapa de "variable" a " valor "pero sin ninguna idea de lo que cualquiera podría desear para estas funciones, no estoy seguro".

Cuestiones relacionadas