2 votes

F# CSVProvider ne signale que les données de la première colonne

firstRow is of type string

Lors de l'utilisation de CSVProvider sur n'importe quel fichier CSV, j'ai utilisé ce qui suit :

http://spatialkeydocs.s3.amazonaws.com/FL_insurance_sample.csv.zip

    type statsProvider = CsvProvider<"../../FL_insurance_sample.csv",",">

    let stats = statsProvider.Load("../../FL_insurance_sample.csv")

    let firstRow = stats.Rows |> Seq.head

Le CSVProvider ne renvoie que les données de la première colonne. Il identifie correctement les colonnes (18) et le nom des colonnes, mais lorsque vous regardez le type des lignes, ils ne sont que de type string, pas un tuple ou une structure...

Comme le montre la capture d'écran, le type de firstRow devrait être un type spécifique, par exemple un tuple ou une structure, pas une chaîne.

Qu'est-ce que je fais de mal? J'utilise Visual Studio 2017, FSharp 4.1, .net 4.5.2 et FSharp.Data 2.3.3

Remarque : cela se produit avec au moins 3 autres fichiers CSV. J'ai choisi ce fichier CSV particulier uniquement à des fins de démonstration.

1voto

rmunn Points 2576

Je ne peux pas reproduire votre problème : le fichier CSV d'exemple que vous avez fourni a très bien fonctionné pour moi. Mais alors, j'utilise VS Code, pas Visual Studio ; il est possible que la source du problème soit quelque part dans Visual Studio 2017 plutôt que dans FSharp.Data. Voici ce que j'ai fait :

  1. Créez un nouveau dossier de projet vide.

  2. Collez le bootstrapper de Paket dedans, dans .paket/paket.bootstrapper.exe.

  3. Exécutez paket init.

  4. Modifiez le fichier paket.dependencies pour ajouter FSharp.Data.

  5. Exécutez paket install.

  6. Exécutez paket generate-load-scripts, qui a créé une série de scripts dans le dossier .paket/load pour charger toutes les dépendances en une fois. (J'adore cette fonctionnalité pour les scripts !)

  7. Créez script.fsx avec le contenu suivant :

    #load ".paket/load/net452/FSharp.Data.fsx"
    open FSharp.Data
    
    type Csv = CsvProvider<"/home/rmunn/Downloads/tmp/csv/FL_insurance_sample.csv">
    let data = Csv.GetSample()
    
    printfn "%A" data.Headers
    
    let firstRow = data.Rows |> Seq.head
    printfn "%A" firstRow
  8. Dans VS Code, sélectionnez l'ensemble du fichier de script et appuyez sur Alt+Enter pour l'envoyer à la fenêtre F# Interactive.

Voici la sortie que j'ai obtenue :

F# Interactive pour F# 4.1
Distribué librement sous la licence Open Source Apache 2.0

Pour obtenir de l'aide, tapez #help;;
> # silentCd @"/home/rmunn/code/fsharp/tmp/foo";;
- # 1 @"/home/rmunn/code/fsharp/tmp/foo/script.fsx"
- ;;

(ignorer la copie de mon script que F# Interactive a renvoyé)

[Chargement /home/rmunn/code/fsharp/tmp/foo/.paket/load/net452/Zlib.Portable.fsx
 Chargement /home/rmunn/code/fsharp/tmp/foo/.paket/load/net452/FSharp.Data.fsx]
namespace FSI_0002.Zlib

namespace FSI_0002.FSharp

Some
  [|"policyID"; "statecode"; "county"; "eq_site_limit"; "hu_site_limit";
    "fl_site_limit"; "fr_site_limit"; "tiv_2011"; "tiv_2012";
    "eq_site_deductible"; "hu_site_deductible"; "fl_site_deductible";
    "fr_site_deductible"; "point_latitude"; "point_longitude"; "line";
    "construction"; "point_granularity"|]
(119736, "FL", "CLAY COUNTY", 498960M, 498960M, 498960M, 498960M, 498960M,
 792148.9M, 0M, 9979.2M, 0, 0, 30.102261M, -81.711777M, "Residential", "Masonry",
 1)
type Csv = FSharp.Data.CsvProvider<...>
val data : FSharp.Data.CsvProvider<...>
val firstRow : FSharp.Data.CsvProvider<...>.Row =
  (119736, "FL", "CLAY COUNTY", 498960M, 498960M, 498960M, 498960M, 498960M,
   792148.9M, 0M, 9979.2M, 0, 0, 30.102261M, -81.711777M, "Residential",
   "Masonry", 1)
val it : unit = ()

Cependant, tout ne s'est pas déroulé entièrement sans problème. Lorsque j'ai ensuite essayé de traiter chaque ligne, j'ai obtenu l'exception suivante :

System.Exception: Impossible de parser la ligne 2439 selon le schéma : Attente de Int32 dans fl_site_deductible, obtenu 68817.6

(J'ai omis la trace car elle ne sera pas particulièrement utile pour vous de savoir à quel numéro de ligne dans FSharp.Data cette exception a été lancée).

La cause de ce problème peut être vue dans la documentation CsvProvider, dans la section "Contrôler les types de colonnes", qui se lit comme suit :

Par défaut, le type provider CSV vérifie les 1 000 premières lignes pour inférer les types, mais vous pouvez le personnaliser en spécifiant le paramètre statique InferRows de CsvProvider. Si vous spécifiez 0, le fichier entier sera utilisé.

Il existe deux façons de résoudre le problème "Inféré int mais aurait dû être décimal". L'une serait d'ajouter InferRows=0 à la définition de votre type CsvProvider. L'autre façon serait de spécifier un schéma explicite pour indiquer au CsvProvider quelles lignes il va mal lire en ne regardant que les 1 000 premières. (Si votre ensemble de données est énorme, cela est bien préférable car examiner toutes les lignes pour inférer les types de données prendrait beaucoup trop de temps). Consultez la documentation pour des exemples, mais vous feriez quelque chose comme Schema="fl_site_deductible=decimal".

Donc si vous ne parvenez pas à faire fonctionner votre code dans Visual Studio, voyez si VS Code (avec les extensions Ionide-Paket, Ionide-FSharp et Ionide-FAKE) fonctionne à la place.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X