significado homogeneos homogeneo homogeneidad heterogéneos heterogeneos heterogeneidad heterogenea grupos ejemplos cultural aula c# .net f#

c# - homogeneos - homogeneidad y heterogeneidad cultural



Trabajar con datos heterogéneos en un lenguaje tipado estáticamente(F#) (3)

Una de las afirmaciones de F # es que permite la creación de scripts interactivos y la exploración / manipulación de datos. He estado jugando con F # tratando de tener una idea de cómo se compara con Matlab y R para el trabajo de análisis de datos. Obviamente, F # no tiene todas las funcionalidades prácticas de estos ecosistemas, pero estoy más interesado en las ventajas / desventajas generales del lenguaje subyacente.

Para mí, el cambio más grande, incluso sobre el estilo funcional, es que F # se escribe de forma estática. Esto tiene cierto atractivo, pero a menudo también se siente como una camisa de fuerza. Por ejemplo, no he encontrado una manera conveniente de tratar con datos rectangulares heterogéneos: piense en el marco de datos en R. Suponga que estoy leyendo un archivo CSV con nombres (cadena) y pesos (flotante). Por lo general, cargo datos, realizo algunas transformaciones, agrego variables, etc. y luego ejecuto el análisis. En R, la primera parte podría verse como:

df <- read.csv(''weights.csv'') df$logweight <- log(df$weight)

En F #, no está claro qué estructura debo usar para hacer esto. Por lo que puedo decir, tengo dos opciones: 1) Puedo definir primero una clase que esté fuertemente tipada (Experto F # 9.10) o 2) Puedo usar un contenedor heterogéneo como ArrayList. Una clase tipificada estáticamente no parece factible porque necesito agregar variables de manera ad hoc (logweight) después de cargar los datos. Un contenedor heterogéneo también es un inconveniente porque cada vez que accedo a una variable necesitaré desempaquetarla. En F #:

let df = readCsv("weights.csv") df.["logweight"] = log(double df.["weight"])

Si esto fuera una o dos veces, podría estar bien, pero especificar un tipo cada vez que uso una variable no parece razonable. A menudo me ocupo de las encuestas con cientos de variables que se agregan / eliminan, se dividen en nuevos subconjuntos y se combinan con otros marcos de datos.

¿Me estoy perdiendo alguna tercera opción obvia? ¿Hay alguna forma ligera y divertida de interactuar y manipular datos heterogéneos? Si necesito hacer un análisis de datos en .Net, mi opinión actual es que debo usar IronPython para todo el trabajo de exploración / transformación / interacción de datos, y solo usar F # / C # para las partes numéricamente intensivas. ¿Es F # inherentemente la herramienta incorrecta para un trabajo de datos heterogéneo rápido y sucio?


¿Es F # inherentemente la herramienta incorrecta para un trabajo de datos heterogéneo rápido y sucio?

Para una minería de datos exploratoria completamente ad hoc, no recomendaría F # ya que los tipos se interpondrían en su camino.

Sin embargo , si sus datos están muy bien definidos, entonces puede mantener tipos de datos dispares en el mismo contenedor al asignar todos sus tipos a una unión F # común:

> #r "FSharp.PowerPack";; --> Referenced ''C:/Program Files/FSharp-1.9.6.16/bin/FSharp.PowerPack.dll'' > let rawData = "Name: Juliet Age: 23 Sex: F Awesome: True" type csv = | Name of string | Age of int | Sex of char | Awesome of bool let parseData data = String.split [''/n''] data |> Seq.map (fun s -> let parts = String.split ['':''] s match parts.[0].Trim(), parts.[1].Trim() with | "Name", x -> Name(x) | "Age", x -> Age(int x) | "Sex", x -> Sex(x.[0]) | "Awesome", x -> Awesome(System.Convert.ToBoolean(x)) | data, _ -> failwithf "Unknown %s" data) |> Seq.to_list;; val rawData : string = "Name: Juliet Age: 23 Sex: F Awesome: True" type csv = | Name of string | Age of int | Sex of char | Awesome of bool val parseData : string -> csv list > parseData rawData;; val it : csv list = [Name "Juliet"; Age 23; Sex ''F''; Awesome true]

csv list está fuertemente tipado y puede hacer un patrón de coincidencia sobre él, pero tiene que definir todos los constructores de su unión por adelantado.

Personalmente, prefiero este enfoque, ya que es un orden de magnitud mejor que trabajar con una ArrayList sin tipo. Sin embargo, no estoy realmente seguro de cuáles son sus requisitos, y no conozco una buena manera de representar variables ad-hoc (excepto tal vez como un Map{string, obj} ) para YMMV.


Creo que hay algunas otras opciones.

(?) operador

Como mencionó Brian, puedes usar el operador (?) :

type dict<''a,''b> = System.Collections.Generic.Dictionary<''a,''b> let (?) (d:dict<_,_>) key = unbox d.[key] let (?<-) (d:dict<_,_>) key value = d.[key] <- box value let df = new dict<string,obj>() df?weight <- 50. df?logWeight <- log(df?weight)

Esto utiliza el boxeo / unboxing en cada acceso, y en ocasiones es posible que necesite agregar anotaciones de tipo:

(* need annotation here, since we could try to unbox at any type *) let fltVal = (df?logWeight : float)

Identificadores de nivel superior

Otra posibilidad es que, en lugar de definir dinámicamente las propiedades de los objetos existentes (que F # no admite particularmente bien), puede usar identificadores de nivel superior.

let dfLogWeight = log(dfWeight)

Esto tiene la ventaja de que casi nunca necesitará especificar tipos, aunque puede saturar su espacio de nombres de nivel superior.

Objetos de propiedad

Una opción final que requiere un poco más de escritura y una sintaxis más fea es crear "objetos de propiedad" fuertemente tipados:

type ''a property = System.Collections.Generic.Dictionary<obj,''a> let createProp() : property<''a> = new property<''a>() let getProp o (prop:property<''a>) : ''a = prop.[o] let setProp o (prop:property<''a>) (value:''a) = prop.[o] <- value let df = new obj() let (weight : property<double>) = createProp() let (logWeight : property<double>) = createProp() setProp df weight 50. setProp df logWeight (getProp df weight) let fltVal = getProp df logWeight

Esto requiere que cada propiedad se cree explícitamente (y requiere una anotación de tipo en ese punto), pero no se necesitarán anotaciones de tipo después de eso. Considero que esto es mucho menos legible que las otras opciones, aunque quizás la definición de un operador para reemplazar a getProp lo alivie un poco.


No estoy seguro si F # es una gran herramienta aquí o no. Pero hay una tercera opción: el operador de signo de interrogación. He estado queriendo bloguear sobre esto por un tiempo ahora; La reciente charla PDC de Luca demostró un lector CSV con C # ''dinámico'', y quería codificar algo similar con F # usando el operador (?). Ver

F # operador "?"

para una breve descripción. Puedes intentar seguir adelante y jugar con esto por tu cuenta, o esperar a que lo publique en el blog. No lo he intentado con seriedad, así que no estoy seguro de qué tan bien funcionará.

EDITAR

Debo agregar que la charla de Luca muestra cómo ''dinámico'' en C # aborda al menos una parte de esta pregunta para ese idioma.

EDITAR

Ver también

http://cs.hubfs.net/forums/thread/12622.aspx

donde publico algun codigo CSV de inicio basico.