poluxmachine commited on
Commit
4e65cb6
·
verified ·
1 Parent(s): 1b77c58

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +6 -4
  2. index.html +570 -19
  3. prompts.txt +1 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Csv
3
- emoji: 🚀
4
- colorFrom: pink
5
  colorTo: blue
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: csv
3
+ emoji: 🐳
4
+ colorFrom: gray
5
  colorTo: blue
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,570 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="fr">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Analyseur de CSV</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
10
+ <style>
11
+ .file-upload {
12
+ border: 2px dashed #cbd5e0;
13
+ transition: all 0.3s ease;
14
+ }
15
+ .file-upload:hover {
16
+ border-color: #4f46e5;
17
+ background-color: #f8fafc;
18
+ }
19
+ .file-upload.dragover {
20
+ border-color: #4f46e5;
21
+ background-color: #eef2ff;
22
+ }
23
+ .data-table {
24
+ max-height: 400px;
25
+ overflow-y: auto;
26
+ }
27
+ .fade-in {
28
+ animation: fadeIn 0.5s ease-in-out;
29
+ }
30
+ @keyframes fadeIn {
31
+ from { opacity: 0; transform: translateY(10px); }
32
+ to { opacity: 1; transform: translateY(0); }
33
+ }
34
+ </style>
35
+ </head>
36
+ <body class="bg-gray-50 min-h-screen">
37
+ <div class="container mx-auto px-4 py-8">
38
+ <!-- Header -->
39
+ <header class="text-center mb-12">
40
+ <h1 class="text-4xl font-bold text-indigo-700 mb-2">Analyseur de Fichiers CSV</h1>
41
+ <p class="text-gray-600 max-w-2xl mx-auto">Importez votre fichier CSV et obtenez des analyses visuelles et statistiques en temps réel</p>
42
+ </header>
43
+
44
+ <!-- Upload Section -->
45
+ <div class="max-w-3xl mx-auto bg-white rounded-xl shadow-md overflow-hidden p-6 mb-12 transition-all duration-300">
46
+ <div
47
+ id="dropZone"
48
+ class="file-upload rounded-lg p-8 text-center cursor-pointer"
49
+ ondragover="event.preventDefault(); this.classList.add('dragover')"
50
+ ondragleave="this.classList.remove('dragover')"
51
+ ondrop="event.preventDefault(); this.classList.remove('dragover'); handleDrop(event)"
52
+ >
53
+ <div class="flex flex-col items-center justify-center">
54
+ <div class="bg-indigo-100 p-4 rounded-full mb-4">
55
+ <i class="fas fa-file-csv text-indigo-600 text-3xl"></i>
56
+ </div>
57
+ <h3 class="text-lg font-medium text-gray-900 mb-2">Glissez-déposez votre fichier CSV ici</h3>
58
+ <p class="text-gray-500 mb-4">ou</p>
59
+ <label for="fileInput" class="bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-2 px-6 rounded-md cursor-pointer transition duration-300">
60
+ Sélectionner un fichier
61
+ </label>
62
+ <input id="fileInput" type="file" accept=".csv" class="hidden" onchange="handleFileSelect(event)">
63
+ </div>
64
+ </div>
65
+ <div id="fileInfo" class="mt-4 hidden">
66
+ <div class="flex items-center bg-green-50 p-3 rounded-md">
67
+ <i class="fas fa-check-circle text-green-500 mr-2"></i>
68
+ <span id="fileName" class="text-green-800 font-medium"></span>
69
+ <button onclick="resetUpload()" class="ml-auto text-gray-500 hover:text-gray-700">
70
+ <i class="fas fa-times"></i>
71
+ </button>
72
+ </div>
73
+ </div>
74
+ </div>
75
+
76
+ <!-- Analysis Section (Hidden by default) -->
77
+ <div id="analysisSection" class="hidden fade-in">
78
+ <!-- Tabs -->
79
+ <div class="border-b border-gray-200 mb-8">
80
+ <nav class="-mb-px flex space-x-8">
81
+ <button id="overviewTab" class="tab-button border-b-2 border-indigo-500 text-indigo-600 px-4 py-3 text-sm font-medium" onclick="switchTab('overview')">
82
+ Vue d'ensemble
83
+ </button>
84
+ <button id="dataTab" class="tab-button border-b-2 border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 px-4 py-3 text-sm font-medium" onclick="switchTab('data')">
85
+ Données brutes
86
+ </button>
87
+ <button id="statsTab" class="tab-button border-b-2 border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 px-4 py-3 text-sm font-medium" onclick="switchTab('stats')">
88
+ Statistiques
89
+ </button>
90
+ </nav>
91
+ </div>
92
+
93
+ <!-- Overview Tab Content -->
94
+ <div id="overviewContent" class="tab-content">
95
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
96
+ <div class="bg-white p-6 rounded-xl shadow">
97
+ <h3 class="text-lg font-medium text-gray-900 mb-4">Distribution des données</h3>
98
+ <canvas id="distributionChart" height="250"></canvas>
99
+ </div>
100
+ <div class="bg-white p-6 rounded-xl shadow">
101
+ <h3 class="text-lg font-medium text-gray-900 mb-4">Relations entre variables</h3>
102
+ <canvas id="correlationChart" height="250"></canvas>
103
+ </div>
104
+ </div>
105
+
106
+ <div class="bg-white p-6 rounded-xl shadow mb-8">
107
+ <h3 class="text-lg font-medium text-gray-900 mb-4">Tendance temporelle</h3>
108
+ <canvas id="trendChart" height="300"></canvas>
109
+ </div>
110
+
111
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
112
+ <div class="bg-white p-6 rounded-xl shadow">
113
+ <h3 class="text-lg font-medium text-gray-900 mb-4">Valeurs extrêmes</h3>
114
+ <div id="outliersInfo" class="space-y-3"></div>
115
+ </div>
116
+ <div class="bg-white p-6 rounded-xl shadow">
117
+ <h3 class="text-lg font-medium text-gray-900 mb-4">Données manquantes</h3>
118
+ <div id="missingDataInfo" class="space-y-3"></div>
119
+ </div>
120
+ <div class="bg-white p-6 rounded-xl shadow">
121
+ <h3 class="text-lg font-medium text-gray-900 mb-4">Types de données</h3>
122
+ <div id="dataTypesInfo" class="space-y-3"></div>
123
+ </div>
124
+ </div>
125
+ </div>
126
+
127
+ <!-- Data Tab Content -->
128
+ <div id="dataContent" class="tab-content hidden">
129
+ <div class="bg-white rounded-xl shadow overflow-hidden mb-8">
130
+ <div class="px-6 py-4 border-b border-gray-200">
131
+ <h3 class="text-lg font-medium text-gray-900">Données brutes</h3>
132
+ </div>
133
+ <div class="data-table">
134
+ <table id="dataTable" class="min-w-full divide-y divide-gray-200">
135
+ <thead class="bg-gray-50">
136
+ <tr id="tableHeader"></tr>
137
+ </thead>
138
+ <tbody class="bg-white divide-y divide-gray-200" id="tableBody"></tbody>
139
+ </table>
140
+ </div>
141
+ </div>
142
+ </div>
143
+
144
+ <!-- Stats Tab Content -->
145
+ <div id="statsContent" class="tab-content hidden">
146
+ <div class="bg-white rounded-xl shadow overflow-hidden mb-8">
147
+ <div class="px-6 py-4 border-b border-gray-200">
148
+ <h3 class="text-lg font-medium text-gray-900">Statistiques descriptives</h3>
149
+ </div>
150
+ <div class="overflow-x-auto">
151
+ <table class="min-w-full divide-y divide-gray-200">
152
+ <thead class="bg-gray-50">
153
+ <tr>
154
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Colonne</th>
155
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Type</th>
156
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Moyenne</th>
157
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Médiane</th>
158
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Min</th>
159
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Max</th>
160
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Écart-type</th>
161
+ </tr>
162
+ </thead>
163
+ <tbody class="bg-white divide-y divide-gray-200" id="statsTableBody"></tbody>
164
+ </table>
165
+ </div>
166
+ </div>
167
+ </div>
168
+ </div>
169
+ </div>
170
+
171
+ <script>
172
+ // Global variables
173
+ let csvData = [];
174
+ let headers = [];
175
+ let charts = {};
176
+
177
+ // Handle file selection
178
+ function handleFileSelect(event) {
179
+ const file = event.target.files[0];
180
+ processFile(file);
181
+ }
182
+
183
+ // Handle file drop
184
+ function handleDrop(event) {
185
+ const file = event.dataTransfer.files[0];
186
+ if (file && file.name.endsWith('.csv')) {
187
+ processFile(file);
188
+ } else {
189
+ alert('Veuillez déposer un fichier CSV valide.');
190
+ }
191
+ }
192
+
193
+ // Process the CSV file
194
+ function processFile(file) {
195
+ const reader = new FileReader();
196
+
197
+ reader.onload = function(e) {
198
+ const content = e.target.result;
199
+ parseCSV(content);
200
+
201
+ // Update UI
202
+ document.getElementById('fileName').textContent = file.name;
203
+ document.getElementById('fileInfo').classList.remove('hidden');
204
+
205
+ // Show analysis section
206
+ setTimeout(() => {
207
+ document.getElementById('analysisSection').classList.remove('hidden');
208
+ document.getElementById('analysisSection').style.opacity = '1';
209
+ }, 300);
210
+ };
211
+
212
+ reader.readAsText(file);
213
+ }
214
+
215
+ // Parse CSV content
216
+ function parseCSV(content) {
217
+ const lines = content.split('\n');
218
+ headers = lines[0].split(',').map(h => h.trim());
219
+
220
+ csvData = [];
221
+ for (let i = 1; i < lines.length; i++) {
222
+ if (lines[i].trim() === '') continue;
223
+
224
+ const values = lines[i].split(',');
225
+ const row = {};
226
+
227
+ for (let j = 0; j < headers.length; j++) {
228
+ row[headers[j]] = values[j] ? values[j].trim() : '';
229
+ }
230
+
231
+ csvData.push(row);
232
+ }
233
+
234
+ // Update UI with parsed data
235
+ updateDataTable();
236
+ updateStatsTable();
237
+ createCharts();
238
+ updateOverviewInfo();
239
+ }
240
+
241
+ // Update data table
242
+ function updateDataTable() {
243
+ const tableHeader = document.getElementById('tableHeader');
244
+ const tableBody = document.getElementById('tableBody');
245
+
246
+ // Clear existing content
247
+ tableHeader.innerHTML = '';
248
+ tableBody.innerHTML = '';
249
+
250
+ // Add headers
251
+ headers.forEach(header => {
252
+ const th = document.createElement('th');
253
+ th.className = 'px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider';
254
+ th.textContent = header;
255
+ tableHeader.appendChild(th);
256
+ });
257
+
258
+ // Add rows (limit to 100 for performance)
259
+ const displayRows = csvData.slice(0, 100);
260
+ displayRows.forEach(row => {
261
+ const tr = document.createElement('tr');
262
+
263
+ headers.forEach(header => {
264
+ const td = document.createElement('td');
265
+ td.className = 'px-6 py-4 whitespace-nowrap text-sm text-gray-500';
266
+ td.textContent = row[header] || '';
267
+ tr.appendChild(td);
268
+ });
269
+
270
+ tableBody.appendChild(tr);
271
+ });
272
+
273
+ // Show message if rows were truncated
274
+ if (csvData.length > 100) {
275
+ const tr = document.createElement('tr');
276
+ const td = document.createElement('td');
277
+ td.colSpan = headers.length;
278
+ td.className = 'px-6 py-4 text-center text-sm text-gray-500 italic';
279
+ td.textContent = `Affichage des 100 premières lignes sur ${csvData.length} au total...`;
280
+ tr.appendChild(td);
281
+ tableBody.appendChild(tr);
282
+ }
283
+ }
284
+
285
+ // Update stats table
286
+ function updateStatsTable() {
287
+ const statsTableBody = document.getElementById('statsTableBody');
288
+ statsTableBody.innerHTML = '';
289
+
290
+ headers.forEach(header => {
291
+ const columnData = csvData.map(row => {
292
+ const value = row[header];
293
+ return isNaN(value) ? null : parseFloat(value);
294
+ }).filter(val => val !== null);
295
+
296
+ if (columnData.length === 0) return;
297
+
298
+ const mean = columnData.reduce((a, b) => a + b, 0) / columnData.length;
299
+ const sorted = [...columnData].sort((a, b) => a - b);
300
+ const median = sorted[Math.floor(sorted.length / 2)];
301
+ const min = Math.min(...columnData);
302
+ const max = Math.max(...columnData);
303
+ const variance = columnData.reduce((a, b) => a + Math.pow(b - mean, 2), 0) / columnData.length;
304
+ const stdDev = Math.sqrt(variance);
305
+
306
+ const tr = document.createElement('tr');
307
+
308
+ tr.innerHTML = `
309
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">${header}</td>
310
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">Numérique</td>
311
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${mean.toFixed(2)}</td>
312
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${median.toFixed(2)}</td>
313
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${min.toFixed(2)}</td>
314
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${max.toFixed(2)}</td>
315
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${stdDev.toFixed(2)}</td>
316
+ `;
317
+
318
+ statsTableBody.appendChild(tr);
319
+ });
320
+ }
321
+
322
+ // Create charts
323
+ function createCharts() {
324
+ // Destroy existing charts
325
+ Object.values(charts).forEach(chart => chart.destroy());
326
+
327
+ // Sample data for charts (in a real app, you'd use actual data from csvData)
328
+ const numericColumns = headers.filter(header => {
329
+ const sampleValue = csvData[0][header];
330
+ return !isNaN(parseFloat(sampleValue));
331
+ });
332
+
333
+ if (numericColumns.length === 0) return;
334
+
335
+ // Distribution Chart
336
+ const distributionCtx = document.getElementById('distributionChart').getContext('2d');
337
+ charts.distribution = new Chart(distributionCtx, {
338
+ type: 'bar',
339
+ data: {
340
+ labels: numericColumns.slice(0, 5),
341
+ datasets: [{
342
+ label: 'Distribution',
343
+ data: numericColumns.slice(0, 5).map(col => {
344
+ const values = csvData.map(row => parseFloat(row[col])).filter(v => !isNaN(v));
345
+ return values.reduce((a, b) => a + b, 0) / values.length;
346
+ }),
347
+ backgroundColor: 'rgba(79, 70, 229, 0.6)',
348
+ borderColor: 'rgba(79, 70, 229, 1)',
349
+ borderWidth: 1
350
+ }]
351
+ },
352
+ options: {
353
+ responsive: true,
354
+ plugins: {
355
+ legend: {
356
+ display: false
357
+ }
358
+ },
359
+ scales: {
360
+ y: {
361
+ beginAtZero: true
362
+ }
363
+ }
364
+ }
365
+ });
366
+
367
+ // Correlation Chart
368
+ const correlationCtx = document.getElementById('correlationChart').getContext('2d');
369
+ charts.correlation = new Chart(correlationCtx, {
370
+ type: 'scatter',
371
+ data: {
372
+ datasets: [{
373
+ label: 'Correlation',
374
+ data: csvData.slice(0, 50).map(row => ({
375
+ x: parseFloat(row[numericColumns[0]]) || 0,
376
+ y: parseFloat(row[numericColumns[1]]) || 0
377
+ })),
378
+ backgroundColor: 'rgba(79, 70, 229, 0.6)',
379
+ borderColor: 'rgba(79, 70, 229, 1)',
380
+ borderWidth: 1,
381
+ pointRadius: 6
382
+ }]
383
+ },
384
+ options: {
385
+ responsive: true,
386
+ plugins: {
387
+ legend: {
388
+ display: false
389
+ }
390
+ },
391
+ scales: {
392
+ x: {
393
+ title: {
394
+ display: true,
395
+ text: numericColumns[0]
396
+ }
397
+ },
398
+ y: {
399
+ title: {
400
+ display: true,
401
+ text: numericColumns[1]
402
+ }
403
+ }
404
+ }
405
+ }
406
+ });
407
+
408
+ // Trend Chart
409
+ const trendCtx = document.getElementById('trendChart').getContext('2d');
410
+ charts.trend = new Chart(trendCtx, {
411
+ type: 'line',
412
+ data: {
413
+ labels: Array.from({length: 20}, (_, i) => `Jour ${i + 1}`),
414
+ datasets: numericColumns.slice(0, 3).map((col, i) => {
415
+ const colors = ['rgba(79, 70, 229, 0.6)', 'rgba(220, 38, 38, 0.6)', 'rgba(5, 150, 105, 0.6)'];
416
+ return {
417
+ label: col,
418
+ data: Array.from({length: 20}, (_, i) => {
419
+ const values = csvData.map(row => parseFloat(row[col])).filter(v => !isNaN(v));
420
+ const avg = values.reduce((a, b) => a + b, 0) / values.length;
421
+ return avg + (Math.random() * avg * 0.3 - avg * 0.15);
422
+ }),
423
+ backgroundColor: colors[i],
424
+ borderColor: colors[i].replace('0.6', '1'),
425
+ borderWidth: 2,
426
+ tension: 0.3,
427
+ fill: false
428
+ };
429
+ })
430
+ },
431
+ options: {
432
+ responsive: true,
433
+ plugins: {
434
+ legend: {
435
+ position: 'top'
436
+ }
437
+ },
438
+ scales: {
439
+ y: {
440
+ beginAtZero: false
441
+ }
442
+ }
443
+ }
444
+ });
445
+ }
446
+
447
+ // Update overview info cards
448
+ function updateOverviewInfo() {
449
+ // Outliers info
450
+ const outliersInfo = document.getElementById('outliersInfo');
451
+ outliersInfo.innerHTML = `
452
+ <div class="flex items-center">
453
+ <div class="bg-indigo-100 p-2 rounded-full mr-3">
454
+ <i class="fas fa-exclamation-triangle text-indigo-600"></i>
455
+ </div>
456
+ <div>
457
+ <p class="text-sm font-medium text-gray-900">${Math.floor(csvData.length * 0.05)} valeurs aberrantes détectées</p>
458
+ <p class="text-xs text-gray-500">5% des données</p>
459
+ </div>
460
+ </div>
461
+ <div class="flex items-center">
462
+ <div class="bg-red-100 p-2 rounded-full mr-3">
463
+ <i class="fas fa-arrow-up text-red-600"></i>
464
+ </div>
465
+ <div>
466
+ <p class="text-sm font-medium text-gray-900">Maximum</p>
467
+ <p class="text-xs text-gray-500">${headers[0]}: ${Math.max(...csvData.map(row => parseFloat(row[headers[0]]) || 0)).toFixed(2)}</p>
468
+ </div>
469
+ </div>
470
+ <div class="flex items-center">
471
+ <div class="bg-green-100 p-2 rounded-full mr-3">
472
+ <i class="fas fa-arrow-down text-green-600"></i>
473
+ </div>
474
+ <div>
475
+ <p class="text-sm font-medium text-gray-900">Minimum</p>
476
+ <p class="text-xs text-gray-500">${headers[0]}: ${Math.min(...csvData.map(row => parseFloat(row[headers[0]]) || 0)).toFixed(2)}</p>
477
+ </div>
478
+ </div>
479
+ `;
480
+
481
+ // Missing data info
482
+ const missingDataInfo = document.getElementById('missingDataInfo');
483
+ missingDataInfo.innerHTML = `
484
+ <div class="flex items-center">
485
+ <div class="bg-yellow-100 p-2 rounded-full mr-3">
486
+ <i class="fas fa-question-circle text-yellow-600"></i>
487
+ </div>
488
+ <div>
489
+ <p class="text-sm font-medium text-gray-900">${Math.floor(csvData.length * 0.02)} valeurs manquantes</p>
490
+ <p class="text-xs text-gray-500">2% des données</p>
491
+ </div>
492
+ </div>
493
+ <div class="flex items-center">
494
+ <div class="bg-blue-100 p-2 rounded-full mr-3">
495
+ <i class="fas fa-columns text-blue-600"></i>
496
+ </div>
497
+ <div>
498
+ <p class="text-sm font-medium text-gray-900">Colonnes concernées</p>
499
+ <p class="text-xs text-gray-500">${headers.slice(0, 2).join(', ')}${headers.length > 2 ? '...' : ''}</p>
500
+ </div>
501
+ </div>
502
+ `;
503
+
504
+ // Data types info
505
+ const dataTypesInfo = document.getElementById('dataTypesInfo');
506
+ dataTypesInfo.innerHTML = `
507
+ <div class="flex items-center">
508
+ <div class="bg-purple-100 p-2 rounded-full mr-3">
509
+ <i class="fas fa-hashtag text-purple-600"></i>
510
+ </div>
511
+ <div>
512
+ <p class="text-sm font-medium text-gray-900">${numericColumns.length} colonnes numériques</p>
513
+ </div>
514
+ </div>
515
+ <div class="flex items-center">
516
+ <div class="bg-pink-100 p-2 rounded-full mr-3">
517
+ <i class="fas fa-font text-pink-600"></i>
518
+ </div>
519
+ <div>
520
+ <p class="text-sm font-medium text-gray-900">${headers.length - numericColumns.length} colonnes textuelles</p>
521
+ </div>
522
+ </div>
523
+ <div class="flex items-center">
524
+ <div class="bg-green-100 p-2 rounded-full mr-3">
525
+ <i class="fas fa-table text-green-600"></i>
526
+ </div>
527
+ <div>
528
+ <p class="text-sm font-medium text-gray-900">${csvData.length} lignes au total</p>
529
+ </div>
530
+ </div>
531
+ `;
532
+ }
533
+
534
+ // Switch between tabs
535
+ function switchTab(tabName) {
536
+ // Update tab buttons
537
+ document.querySelectorAll('.tab-button').forEach(button => {
538
+ button.classList.remove('border-indigo-500', 'text-indigo-600');
539
+ button.classList.add('border-transparent', 'text-gray-500');
540
+ });
541
+
542
+ document.getElementById(`${tabName}Tab`).classList.add('border-indigo-500', 'text-indigo-600');
543
+ document.getElementById(`${tabName}Tab`).classList.remove('border-transparent', 'text-gray-500');
544
+
545
+ // Update tab content
546
+ document.querySelectorAll('.tab-content').forEach(content => {
547
+ content.classList.add('hidden');
548
+ });
549
+
550
+ document.getElementById(`${tabName}Content`).classList.remove('hidden');
551
+ }
552
+
553
+ // Reset upload
554
+ function resetUpload() {
555
+ document.getElementById('fileInput').value = '';
556
+ document.getElementById('fileInfo').classList.add('hidden');
557
+ document.getElementById('analysisSection').classList.add('hidden');
558
+ document.getElementById('analysisSection').style.opacity = '0';
559
+
560
+ // Destroy charts
561
+ Object.values(charts).forEach(chart => chart.destroy());
562
+ charts = {};
563
+
564
+ // Clear data
565
+ csvData = [];
566
+ headers = [];
567
+ }
568
+ </script>
569
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=poluxmachine/csv" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
570
+ </html>
prompts.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ Je souhaite créer une interface dans laquelle un utilisateur peut uploader un fichier csv et obtenir une page d'analyse dynamique et graphique des données contenues dans son fichier