guillermo2323 commited on
Commit
f04db80
·
verified ·
1 Parent(s): 43428f3

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +566 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Ggplotgrahs Like App
3
- emoji: 😻
4
- colorFrom: gray
5
- colorTo: red
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: ggplotgrahs-like-app
3
+ emoji: 🐳
4
+ colorFrom: blue
5
+ colorTo: green
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,566 @@
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="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>3D ggplot2 Simulator</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
9
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.3.0/papaparse.min.js"></script>
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
11
+ <style>
12
+ .plot-container {
13
+ transition: all 0.3s ease;
14
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
15
+ }
16
+ .plot-container:hover {
17
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
18
+ }
19
+ .theme-btn {
20
+ transition: all 0.2s ease;
21
+ }
22
+ .theme-btn:hover {
23
+ transform: scale(1.05);
24
+ }
25
+ .control-panel {
26
+ backdrop-filter: blur(10px);
27
+ background-color: rgba(255, 255, 255, 0.85);
28
+ }
29
+ @media (max-width: 768px) {
30
+ .control-panel {
31
+ width: 100%;
32
+ margin-left: 0;
33
+ }
34
+ }
35
+ .file-upload-label {
36
+ transition: all 0.3s ease;
37
+ }
38
+ .file-upload-label:hover {
39
+ background-color: #4f46e5;
40
+ color: white;
41
+ }
42
+ </style>
43
+ </head>
44
+ <body class="bg-gray-50 min-h-screen">
45
+ <div class="container mx-auto px-4 py-8">
46
+ <!-- Header -->
47
+ <header class="mb-8 text-center">
48
+ <h1 class="text-4xl font-bold text-indigo-800 mb-2">3D ggplot2 Simulator</h1>
49
+ <p class="text-lg text-gray-600">Create beautiful 3D visualizations with ggplot2-inspired aesthetics</p>
50
+ </header>
51
+
52
+ <div class="flex flex-col lg:flex-row gap-8">
53
+ <!-- Main Visualization Area -->
54
+ <div class="flex-1">
55
+ <div class="bg-white rounded-xl p-4 plot-container" id="plot-container">
56
+ <div id="3d-plot" class="w-full h-[500px]"></div>
57
+ </div>
58
+
59
+ <!-- Sample Data Section -->
60
+ <div class="mt-6 bg-white rounded-xl p-6 shadow-sm">
61
+ <h3 class="text-xl font-semibold text-gray-800 mb-4">Try Sample Datasets</h3>
62
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
63
+ <button onclick="loadSampleData('iris')" class="bg-indigo-100 hover:bg-indigo-200 text-indigo-800 py-3 px-4 rounded-lg flex items-center justify-center transition-colors">
64
+ <i class="fas fa-seedling mr-2"></i> Iris Dataset
65
+ </button>
66
+ <button onclick="loadSampleData('mtcars')" class="bg-indigo-100 hover:bg-indigo-200 text-indigo-800 py-3 px-4 rounded-lg flex items-center justify-center transition-colors">
67
+ <i class="fas fa-car mr-2"></i> mtcars Dataset
68
+ </button>
69
+ <button onclick="loadSampleData('random')" class="bg-indigo-100 hover:bg-indigo-200 text-indigo-800 py-3 px-4 rounded-lg flex items-center justify-center transition-colors">
70
+ <i class="fas fa-random mr-2"></i> Random Data
71
+ </button>
72
+ </div>
73
+ </div>
74
+ </div>
75
+
76
+ <!-- Control Panel -->
77
+ <div class="lg:w-80 control-panel p-6 rounded-xl shadow-sm sticky top-4">
78
+ <h2 class="text-xl font-bold text-gray-800 mb-6 flex items-center">
79
+ <i class="fas fa-sliders-h mr-2 text-indigo-600"></i> Controls
80
+ </h2>
81
+
82
+ <!-- Data Upload -->
83
+ <div class="mb-6">
84
+ <label class="block text-sm font-medium text-gray-700 mb-2">Upload Your Data (CSV)</label>
85
+ <label for="file-upload" class="file-upload-label cursor-pointer flex items-center justify-center border-2 border-dashed border-indigo-300 rounded-lg py-3 px-4 text-indigo-600 hover:bg-indigo-50">
86
+ <i class="fas fa-cloud-upload-alt mr-2"></i>
87
+ <span>Choose File</span>
88
+ <input id="file-upload" type="file" class="hidden" accept=".csv" onchange="handleFileUpload(event)">
89
+ </label>
90
+ <div id="file-name" class="text-sm text-gray-500 mt-2"></div>
91
+ </div>
92
+
93
+ <!-- Variable Selection -->
94
+ <div class="mb-6">
95
+ <h3 class="text-sm font-medium text-gray-700 mb-3 flex items-center">
96
+ <i class="fas fa-table mr-2"></i> Variable Mapping
97
+ </h3>
98
+ <div class="space-y-4">
99
+ <div>
100
+ <label class="block text-xs font-medium text-gray-500 mb-1">X Axis</label>
101
+ <select id="x-axis" class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 py-2 px-3 border">
102
+ <option value="">Select variable</option>
103
+ </select>
104
+ </div>
105
+ <div>
106
+ <label class="block text-xs font-medium text-gray-500 mb-1">Y Axis</label>
107
+ <select id="y-axis" class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 py-2 px-3 border">
108
+ <option value="">Select variable</option>
109
+ </select>
110
+ </div>
111
+ <div>
112
+ <label class="block text-xs font-medium text-gray-500 mb-1">Z Axis</label>
113
+ <select id="z-axis" class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 py-2 px-3 border">
114
+ <option value="">Select variable</option>
115
+ </select>
116
+ </div>
117
+ <div>
118
+ <label class="block text-xs font-medium text-gray-500 mb-1">Color By</label>
119
+ <select id="color-by" class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 py-2 px-3 border">
120
+ <option value="">None (single color)</option>
121
+ </select>
122
+ </div>
123
+ </div>
124
+ </div>
125
+
126
+ <!-- Plot Customization -->
127
+ <div class="mb-6">
128
+ <h3 class="text-sm font-medium text-gray-700 mb-3 flex items-center">
129
+ <i class="fas fa-paint-brush mr-2"></i> Plot Customization
130
+ </h3>
131
+ <div class="space-y-4">
132
+ <div>
133
+ <label class="block text-xs font-medium text-gray-500 mb-1">Plot Type</label>
134
+ <select id="plot-type" class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 py-2 px-3 border">
135
+ <option value="scatter">Scatter Plot</option>
136
+ <option value="surface">Surface Plot</option>
137
+ <option value="line">Line Plot</option>
138
+ </select>
139
+ </div>
140
+ <div>
141
+ <label class="block text-xs font-medium text-gray-500 mb-1">Point Size</label>
142
+ <input id="point-size" type="range" min="1" max="20" value="5" class="w-full">
143
+ </div>
144
+ <div>
145
+ <label class="block text-xs font-medium text-gray-500 mb-1">Opacity</label>
146
+ <input id="opacity" type="range" min="0.1" max="1" step="0.1" value="0.8" class="w-full">
147
+ </div>
148
+ </div>
149
+ </div>
150
+
151
+ <!-- Theme Selection -->
152
+ <div class="mb-6">
153
+ <h3 class="text-sm font-medium text-gray-700 mb-3 flex items-center">
154
+ <i class="fas fa-palette mr-2"></i> Color Theme
155
+ </h3>
156
+ <div class="grid grid-cols-3 gap-2">
157
+ <button onclick="setTheme('ggplot')" class="theme-btn bg-white border border-gray-200 rounded-md p-2 hover:border-indigo-400">
158
+ <div class="h-4 w-full bg-gradient-to-r from-blue-400 via-green-500 to-red-500 rounded-sm mb-1"></div>
159
+ <span class="text-xs">ggplot</span>
160
+ </button>
161
+ <button onclick="setTheme('viridis')" class="theme-btn bg-white border border-gray-200 rounded-md p-2 hover:border-indigo-400">
162
+ <div class="h-4 w-full bg-gradient-to-r from-purple-500 via-teal-500 to-yellow-500 rounded-sm mb-1"></div>
163
+ <span class="text-xs">Viridis</span>
164
+ </button>
165
+ <button onclick="setTheme('plasma')" class="theme-btn bg-white border border-gray-200 rounded-md p-2 hover:border-indigo-400">
166
+ <div class="h-4 w-full bg-gradient-to-r from-purple-700 via-pink-500 to-yellow-300 rounded-sm mb-1"></div>
167
+ <span class="text-xs">Plasma</span>
168
+ </button>
169
+ <button onclick="setTheme('magma')" class="theme-btn bg-white border border-gray-200 rounded-md p-2 hover:border-indigo-400">
170
+ <div class="h-4 w-full bg-gradient-to-r from-black via-red-900 to-yellow-200 rounded-sm mb-1"></div>
171
+ <span class="text-xs">Magma</span>
172
+ </button>
173
+ <button onclick="setTheme('cividis')" class="theme-btn bg-white border border-gray-200 rounded-md p-2 hover:border-indigo-400">
174
+ <div class="h-4 w-full bg-gradient-to-r from-blue-900 via-yellow-300 to-yellow-100 rounded-sm mb-1"></div>
175
+ <span class="text-xs">Cividis</span>
176
+ </button>
177
+ <button onclick="setTheme('custom')" class="theme-btn bg-white border border-gray-200 rounded-md p-2 hover:border-indigo-400">
178
+ <div class="h-4 w-full bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500 rounded-sm mb-1"></div>
179
+ <span class="text-xs">Custom</span>
180
+ </button>
181
+ </div>
182
+ </div>
183
+
184
+ <!-- Update Button -->
185
+ <button onclick="updatePlot()" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white py-2 px-4 rounded-md flex items-center justify-center transition-colors">
186
+ <i class="fas fa-sync-alt mr-2"></i> Update Visualization
187
+ </button>
188
+
189
+ <!-- Export Options -->
190
+ <div class="mt-6 pt-4 border-t border-gray-200">
191
+ <h3 class="text-sm font-medium text-gray-700 mb-3 flex items-center">
192
+ <i class="fas fa-download mr-2"></i> Export
193
+ </h3>
194
+ <div class="grid grid-cols-2 gap-2">
195
+ <button onclick="exportPNG()" class="bg-gray-100 hover:bg-gray-200 text-gray-800 py-2 px-3 rounded-md text-sm flex items-center justify-center">
196
+ <i class="fas fa-image mr-2"></i> PNG
197
+ </button>
198
+ <button onclick="exportSVG()" class="bg-gray-100 hover:bg-gray-200 text-gray-800 py-2 px-3 rounded-md text-sm flex items-center justify-center">
199
+ <i class="fas fa-file-image mr-2"></i> SVG
200
+ </button>
201
+ </div>
202
+ </div>
203
+ </div>
204
+ </div>
205
+ </div>
206
+
207
+ <script>
208
+ // Global variables
209
+ let currentData = [];
210
+ let currentColumns = [];
211
+ let currentTheme = 'ggplot';
212
+
213
+ // Initialize with sample data
214
+ document.addEventListener('DOMContentLoaded', function() {
215
+ loadSampleData('iris');
216
+ });
217
+
218
+ // Load sample datasets
219
+ function loadSampleData(dataset) {
220
+ let data, columns;
221
+
222
+ switch(dataset) {
223
+ case 'iris':
224
+ data = [
225
+ {sepal_length: 5.1, sepal_width: 3.5, petal_length: 1.4, petal_width: 0.2, species: 'setosa'},
226
+ {sepal_length: 4.9, sepal_width: 3.0, petal_length: 1.4, petal_width: 0.2, species: 'setosa'},
227
+ {sepal_length: 4.7, sepal_width: 3.2, petal_length: 1.3, petal_width: 0.2, species: 'setosa'},
228
+ {sepal_length: 6.3, sepal_width: 3.3, petal_length: 6.0, petal_width: 2.5, species: 'virginica'},
229
+ {sepal_length: 5.8, sepal_width: 2.7, petal_length: 5.1, petal_width: 1.9, species: 'virginica'},
230
+ {sepal_length: 7.1, sepal_width: 3.0, petal_length: 5.9, petal_width: 2.1, species: 'virginica'},
231
+ {sepal_length: 6.3, sepal_width: 2.9, petal_length: 5.6, petal_width: 1.8, species: 'virginica'},
232
+ {sepal_length: 6.5, sepal_width: 3.0, petal_length: 5.8, petal_width: 2.2, species: 'virginica'},
233
+ {sepal_length: 7.6, sepal_width: 3.0, petal_length: 6.6, petal_width: 2.1, species: 'virginica'},
234
+ {sepal_length: 4.9, sepal_width: 2.5, petal_length: 4.5, petal_width: 1.7, species: 'versicolor'},
235
+ {sepal_length: 7.3, sepal_width: 2.9, petal_length: 6.3, petal_width: 1.8, species: 'virginica'},
236
+ {sepal_length: 6.7, sepal_width: 2.5, petal_length: 5.8, petal_width: 1.8, species: 'virginica'},
237
+ {sepal_length: 7.2, sepal_width: 3.6, petal_length: 6.1, petal_width: 2.5, species: 'virginica'},
238
+ {sepal_length: 6.5, sepal_width: 3.2, petal_length: 5.1, petal_width: 2.0, species: 'virginica'},
239
+ {sepal_length: 6.4, sepal_width: 2.7, petal_length: 5.3, petal_width: 1.9, species: 'virginica'},
240
+ {sepal_length: 6.8, sepal_width: 3.0, petal_length: 5.5, petal_width: 2.1, species: 'virginica'},
241
+ {sepal_length: 5.7, sepal_width: 2.5, petal_length: 5.0, petal_width: 2.0, species: 'virginica'},
242
+ {sepal_length: 5.8, sepal_width: 2.8, petal_length: 5.1, petal_width: 2.4, species: 'virginica'},
243
+ {sepal_length: 6.4, sepal_width: 3.2, petal_length: 5.3, petal_width: 2.3, species: 'virginica'},
244
+ {sepal_length: 6.5, sepal_width: 3.0, petal_length: 5.5, petal_width: 1.8, species: 'virginica'},
245
+ {sepal_length: 7.7, sepal_width: 3.8, petal_length: 6.7, petal_width: 2.2, species: 'virginica'},
246
+ {sepal_length: 7.7, sepal_width: 2.6, petal_length: 6.9, petal_width: 2.3, species: 'virginica'},
247
+ {sepal_length: 6.0, sepal_width: 2.2, petal_length: 5.0, petal_width: 1.5, species: 'virginica'},
248
+ {sepal_length: 6.9, sepal_width: 3.2, petal_length: 5.7, petal_width: 2.3, species: 'virginica'},
249
+ {sepal_length: 5.6, sepal_width: 2.8, petal_length: 4.9, petal_width: 2.0, species: 'virginica'},
250
+ {sepal_length: 7.7, sepal_width: 2.8, petal_length: 6.7, petal_width: 2.0, species: 'virginica'},
251
+ {sepal_length: 6.3, sepal_width: 2.7, petal_length: 4.9, petal_width: 1.8, species: 'virginica'},
252
+ {sepal_length: 6.7, sepal_width: 3.3, petal_length: 5.7, petal_width: 2.1, species: 'virginica'},
253
+ {sepal_length: 7.2, sepal_width: 3.2, petal_length: 6.0, petal_width: 1.8, species: 'virginica'},
254
+ {sepal_length: 6.2, sepal_width: 2.8, petal_length: 4.8, petal_width: 1.8, species: 'virginica'},
255
+ {sepal_length: 6.1, sepal_width: 3.0, petal_length: 4.9, petal_width: 1.8, species: 'virginica'},
256
+ {sepal_length: 6.4, sepal_width: 2.8, petal_length: 5.6, petal_width: 2.1, species: 'virginica'},
257
+ {sepal_length: 7.2, sepal_width: 3.0, petal_length: 5.8, petal_width: 1.6, species: 'virginica'},
258
+ {sepal_length: 7.4, sepal_width: 2.8, petal_length: 6.1, petal_width: 1.9, species: 'virginica'},
259
+ {sepal_length: 7.9, sepal_width: 3.8, petal_length: 6.4, petal_width: 2.0, species: 'virginica'},
260
+ {sepal_length: 6.4, sepal_width: 2.8, petal_length: 5.6, petal_width: 2.2, species: 'virginica'},
261
+ {sepal_length: 6.3, sepal_width: 2.8, petal_length: 5.1, petal_width: 1.5, species: 'virginica'},
262
+ {sepal_length: 6.1, sepal_width: 2.6, petal_length: 5.6, petal_width: 1.4, species: 'virginica'},
263
+ {sepal_length: 7.7, sepal_width: 3.0, petal_length: 6.1, petal_width: 2.3, species: 'virginica'},
264
+ {sepal_length: 6.3, sepal_width: 3.4, petal_length: 5.6, petal_width: 2.4, species: 'virginica'},
265
+ {sepal_length: 6.4, sepal_width: 3.1, petal_length: 5.5, petal_width: 1.8, species: 'virginica'},
266
+ {sepal_length: 6.0, sepal_width: 3.0, petal_length: 4.8, petal_width: 1.8, species: 'virginica'},
267
+ {sepal_length: 6.9, sepal_width: 3.1, petal_length: 5.4, petal_width: 2.1, species: 'virginica'},
268
+ {sepal_length: 6.7, sepal_width: 3.1, petal_length: 5.6, petal_width: 2.4, species: 'virginica'},
269
+ {sepal_length: 6.9, sepal_width: 3.1, petal_length: 5.1, petal_width: 2.3, species: 'virginica'},
270
+ {sepal_length: 5.8, sepal_width: 2.7, petal_length: 5.1, petal_width: 1.9, species: 'virginica'},
271
+ {sepal_length: 6.8, sepal_width: 3.2, petal_length: 5.9, petal_width: 2.3, species: 'virginica'},
272
+ {sepal_length: 6.7, sepal_width: 3.3, petal_length: 5.7, petal_width: 2.5, species: 'virginica'},
273
+ {sepal_length: 6.7, sepal_width: 3.0, petal_length: 5.2, petal_width: 2.3, species: 'virginica'},
274
+ {sepal_length: 6.3, sepal_width: 2.5, petal_length: 5.0, petal_width: 1.9, species: 'virginica'},
275
+ {sepal_length: 6.5, sepal_width: 3.0, petal_length: 5.2, petal_width: 2.0, species: 'virginica'},
276
+ {sepal_length: 6.2, sepal_width: 3.4, petal_length: 5.4, petal_width: 2.3, species: 'virginica'},
277
+ {sepal_length: 5.9, sepal_width: 3.0, petal_length: 5.1, petal_width: 1.8, species: 'virginica'}
278
+ ];
279
+ columns = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'species'];
280
+ break;
281
+
282
+ case 'mtcars':
283
+ data = [
284
+ {mpg: 21.0, cyl: 6, disp: 160, hp: 110, drat: 3.90, wt: 2.620, qsec: 16.46, vs: 0, am: 1, gear: 4, carb: 4, model: "Mazda RX4"},
285
+ {mpg: 21.0, cyl: 6, disp: 160, hp: 110, drat: 3.90, wt: 2.875, qsec: 17.02, vs: 0, am: 1, gear: 4, carb: 4, model: "Mazda RX4 Wag"},
286
+ {mpg: 22.8, cyl: 4, disp: 108, hp: 93, drat: 3.85, wt: 2.320, qsec: 18.61, vs: 1, am: 1, gear: 4, carb: 1, model: "Datsun 710"},
287
+ {mpg: 21.4, cyl: 6, disp: 258, hp: 110, drat: 3.08, wt: 3.215, qsec: 19.44, vs: 1, am: 0, gear: 3, carb: 1, model: "Hornet 4 Drive"},
288
+ {mpg: 18.7, cyl: 8, disp: 360, hp: 175, drat: 3.15, wt: 3.440, qsec: 17.02, vs: 0, am: 0, gear: 3, carb: 2, model: "Hornet Sportabout"},
289
+ {mpg: 18.1, cyl: 6, disp: 225, hp: 105, drat: 2.76, wt: 3.460, qsec: 20.22, vs: 1, am: 0, gear: 3, carb: 1, model: "Valiant"},
290
+ {mpg: 14.3, cyl: 8, disp: 360, hp: 245, drat: 3.21, wt: 3.570, qsec: 15.84, vs: 0, am: 0, gear: 3, carb: 4, model: "Duster 360"},
291
+ {mpg: 24.4, cyl: 4, disp: 146.7, hp: 62, drat: 3.69, wt: 3.190, qsec: 20.00, vs: 1, am: 0, gear: 4, carb: 2, model: "Merc 240D"},
292
+ {mpg: 22.8, cyl: 4, disp: 140.8, hp: 95, drat: 3.92, wt: 3.150, qsec: 22.90, vs: 1, am: 0, gear: 4, carb: 2, model: "Merc 230"},
293
+ {mpg: 19.2, cyl: 6, disp: 167.6, hp: 123, drat: 3.92, wt: 3.440, qsec: 18.30, vs: 1, am: 0, gear: 4, carb: 4, model: "Merc 280"},
294
+ {mpg: 17.8, cyl: 6, disp: 167.6, hp: 123, drat: 3.92, wt: 3.440, qsec: 18.90, vs: 1, am: 0, gear: 4, carb: 4, model: "Merc 280C"},
295
+ {mpg: 16.4, cyl: 8, disp: 275.8, hp: 180, drat: 3.07, wt: 4.070, qsec: 17.40, vs: 0, am: 0, gear: 3, carb: 3, model: "Merc 450SE"},
296
+ {mpg: 17.3, cyl: 8, disp: 275.8, hp: 180, drat: 3.07, wt: 3.730, qsec: 17.60, vs: 0, am: 0, gear: 3, carb: 3, model: "Merc 450SL"},
297
+ {mpg: 15.2, cyl: 8, disp: 275.8, hp: 180, drat: 3.07, wt: 3.780, qsec: 18.00, vs: 0, am: 0, gear: 3, carb: 3, model: "Merc 450SLC"},
298
+ {mpg: 10.4, cyl: 8, disp: 472, hp: 205, drat: 2.93, wt: 5.250, qsec: 17.98, vs: 0, am: 0, gear: 3, carb: 4, model: "Cadillac Fleetwood"},
299
+ {mpg: 10.4, cyl: 8, disp: 460, hp: 215, drat: 3.00, wt: 5.424, qsec: 17.82, vs: 0, am: 0, gear: 3, carb: 4, model: "Lincoln Continental"},
300
+ {mpg: 14.7, cyl: 8, disp: 440, hp: 230, drat: 3.23, wt: 5.345, qsec: 17.42, vs: 0, am: 0, gear: 3, carb: 4, model: "Chrysler Imperial"},
301
+ {mpg: 32.4, cyl: 4, disp: 78.7, hp: 66, drat: 4.08, wt: 2.200, qsec: 19.47, vs: 1, am: 1, gear: 4, carb: 1, model: "Fiat 128"},
302
+ {mpg: 30.4, cyl: 4, disp: 75.7, hp: 52, drat: 4.93, wt: 1.615, qsec: 18.52, vs: 1, am: 1, gear: 4, carb: 2, model: "Honda Civic"},
303
+ {mpg: 33.9, cyl: 4, disp: 71.1, hp: 65, drat: 4.22, wt: 1.835, qsec: 19.90, vs: 1, am: 1, gear: 4, carb: 1, model: "Toyota Corolla"},
304
+ {mpg: 21.5, cyl: 4, disp: 120.1, hp: 97, drat: 3.70, wt: 2.465, qsec: 20.01, vs: 1, am: 0, gear: 3, carb: 1, model: "Toyota Corona"},
305
+ {mpg: 15.5, cyl: 8, disp: 318, hp: 150, drat: 2.76, wt: 3.520, qsec: 16.87, vs: 0, am: 0, gear: 3, carb: 2, model: "Dodge Challenger"},
306
+ {mpg: 15.2, cyl: 8, disp: 304, hp: 150, drat: 3.15, wt: 3.435, qsec: 17.30, vs: 0, am: 0, gear: 3, carb: 2, model: "AMC Javelin"},
307
+ {mpg: 13.3, cyl: 8, disp: 350, hp: 245, drat: 3.73, wt: 3.840, qsec: 15.41, vs: 0, am: 0, gear: 3, carb: 4, model: "Camaro Z28"},
308
+ {mpg: 19.2, cyl: 8, disp: 400, hp: 175, drat: 3.08, wt: 3.845, qsec: 17.05, vs: 0, am: 0, gear: 3, carb: 2, model: "Pontiac Firebird"},
309
+ {mpg: 27.3, cyl: 4, disp: 79, hp: 66, drat: 4.08, wt: 1.935, qsec: 18.90, vs: 1, am: 1, gear: 4, carb: 1, model: "Fiat X1-9"},
310
+ {mpg: 26, cyl: 4, disp: 120.3, hp: 91, drat: 4.43, wt: 2.140, qsec: 16.70, vs: 0, am: 1, gear: 5, carb: 2, model: "Porsche 914-2"},
311
+ {mpg: 30.4, cyl: 4, disp: 95.1, hp: 113, drat: 3.77, wt: 1.513, qsec: 16.90, vs: 1, am: 1, gear: 5, carb: 2, model: "Lotus Europa"},
312
+ {mpg: 15.8, cyl: 8, disp: 351, hp: 264, drat: 4.22, wt: 3.170, qsec: 14.50, vs: 0, am: 1, gear: 5, carb: 4, model: "Ford Pantera L"},
313
+ {mpg: 19.7, cyl: 6, disp: 145, hp: 175, drat: 3.62, wt: 2.770, qsec: 15.50, vs: 0, am: 1, gear: 5, carb: 6, model: "Ferrari Dino"},
314
+ {mpg: 15, cyl: 8, disp: 301, hp: 335, drat: 3.54, wt: 3.570, qsec: 14.60, vs: 0, am: 1, gear: 5, carb: 8, model: "Maserati Bora"},
315
+ {mpg: 21.4, cyl: 4, disp: 121, hp: 109, drat: 4.11, wt: 2.780, qsec: 18.60, vs: 1, am: 1, gear: 4, carb: 2, model: "Volvo 142E"}
316
+ ];
317
+ columns = ['mpg', 'cyl', 'disp', 'hp', 'drat', 'wt', 'qsec', 'vs', 'am', 'gear', 'carb', 'model'];
318
+ break;
319
+
320
+ case 'random':
321
+ data = [];
322
+ columns = ['x', 'y', 'z', 'category'];
323
+ for (let i = 0; i < 100; i++) {
324
+ data.push({
325
+ x: Math.random() * 10,
326
+ y: Math.random() * 10,
327
+ z: Math.random() * 10,
328
+ category: Math.random() > 0.5 ? 'A' : 'B'
329
+ });
330
+ }
331
+ break;
332
+ }
333
+
334
+ currentData = data;
335
+ currentColumns = columns;
336
+ updateColumnSelectors();
337
+ updatePlot();
338
+
339
+ // Update sample data indicator
340
+ document.getElementById('file-name').textContent = `Loaded: ${dataset} dataset`;
341
+ }
342
+
343
+ // Handle file upload
344
+ function handleFileUpload(event) {
345
+ const file = event.target.files[0];
346
+ if (!file) return;
347
+
348
+ document.getElementById('file-name').textContent = `Uploading: ${file.name}`;
349
+
350
+ Papa.parse(file, {
351
+ header: true,
352
+ complete: function(results) {
353
+ currentData = results.data;
354
+ currentColumns = results.meta.fields;
355
+ updateColumnSelectors();
356
+ updatePlot();
357
+
358
+ document.getElementById('file-name').textContent = `Loaded: ${file.name}`;
359
+ },
360
+ error: function(error) {
361
+ console.error("Error parsing CSV:", error);
362
+ document.getElementById('file-name').textContent = `Error loading file`;
363
+ }
364
+ });
365
+ }
366
+
367
+ // Update column selectors
368
+ function updateColumnSelectors() {
369
+ const xAxis = document.getElementById('x-axis');
370
+ const yAxis = document.getElementById('y-axis');
371
+ const zAxis = document.getElementById('z-axis');
372
+ const colorBy = document.getElementById('color-by');
373
+
374
+ // Clear existing options
375
+ xAxis.innerHTML = '<option value="">Select variable</option>';
376
+ yAxis.innerHTML = '<option value="">Select variable</option>';
377
+ zAxis.innerHTML = '<option value="">Select variable</option>';
378
+ colorBy.innerHTML = '<option value="">None (single color)</option>';
379
+
380
+ // Add new options
381
+ currentColumns.forEach(col => {
382
+ const option = document.createElement('option');
383
+ option.value = col;
384
+ option.textContent = col;
385
+
386
+ xAxis.appendChild(option.cloneNode(true));
387
+ yAxis.appendChild(option.cloneNode(true));
388
+ zAxis.appendChild(option.cloneNode(true));
389
+ colorBy.appendChild(option.cloneNode(true));
390
+ });
391
+
392
+ // Set default selections if possible
393
+ if (currentColumns.includes('x') || currentColumns.includes('X')) {
394
+ xAxis.value = currentColumns.includes('x') ? 'x' : 'X';
395
+ }
396
+ if (currentColumns.includes('y') || currentColumns.includes('Y')) {
397
+ yAxis.value = currentColumns.includes('y') ? 'y' : 'Y';
398
+ }
399
+ if (currentColumns.includes('z') || currentColumns.includes('Z')) {
400
+ zAxis.value = currentColumns.includes('z') ? 'z' : 'Z';
401
+ }
402
+ if (currentColumns.includes('category') || currentColumns.includes('group')) {
403
+ colorBy.value = currentColumns.includes('category') ? 'category' : 'group';
404
+ }
405
+ }
406
+
407
+ // Set color theme
408
+ function setTheme(theme) {
409
+ currentTheme = theme;
410
+ updatePlot();
411
+ }
412
+
413
+ // Get color scale based on current theme
414
+ function getColorScale() {
415
+ switch(currentTheme) {
416
+ case 'ggplot':
417
+ return ['#619CFF', '#00BA38', '#F8766D'];
418
+ case 'viridis':
419
+ return ['#440154', '#3B528B', '#21908C', '#5DC963', '#FDE725'];
420
+ case 'plasma':
421
+ return ['#0D0887', '#7E03A8', '#CC4678', '#F89441', '#F0F921'];
422
+ case 'magma':
423
+ return ['#000004', '#3B0F70', '#8C2981', '#DE4968', '#FE9F6D', '#FCFDBF'];
424
+ case 'cividis':
425
+ return ['#00204D', '#31446B', '#666870', '#958F78', '#D1BC5F', '#FDE333'];
426
+ case 'custom':
427
+ return ['#6366F1', '#8B5CF6', '#EC4899'];
428
+ default:
429
+ return ['#6366F1', '#8B5CF6', '#EC4899'];
430
+ }
431
+ }
432
+
433
+ // Update the 3D plot
434
+ function updatePlot() {
435
+ const xAxis = document.getElementById('x-axis').value;
436
+ const yAxis = document.getElementById('y-axis').value;
437
+ const zAxis = document.getElementById('z-axis').value;
438
+ const colorBy = document.getElementById('color-by').value;
439
+ const plotType = document.getElementById('plot-type').value;
440
+ const pointSize = document.getElementById('point-size').value;
441
+ const opacity = document.getElementById('opacity').value;
442
+
443
+ if (!xAxis || !yAxis || !zAxis) {
444
+ alert("Please select X, Y, and Z axes variables");
445
+ return;
446
+ }
447
+
448
+ // Prepare data for plotting
449
+ let traces = [];
450
+ const colorScale = getColorScale();
451
+
452
+ if (colorBy && currentColumns.includes(colorBy)) {
453
+ // Group data by color variable
454
+ const groups = {};
455
+ currentData.forEach(row => {
456
+ const groupValue = row[colorBy];
457
+ if (!groups[groupValue]) {
458
+ groups[groupValue] = {
459
+ x: [],
460
+ y: [],
461
+ z: [],
462
+ text: []
463
+ };
464
+ }
465
+ groups[groupValue].x.push(row[xAxis]);
466
+ groups[groupValue].y.push(row[yAxis]);
467
+ groups[groupValue].z.push(row[zAxis]);
468
+ groups[groupValue].text.push(Object.entries(row).map(([key, val]) => `${key}: ${val}`).join('<br>'));
469
+ });
470
+
471
+ // Create a trace for each group
472
+ const groupValues = Object.keys(groups);
473
+ groupValues.forEach((group, i) => {
474
+ const colorIndex = i % colorScale.length;
475
+ const trace = {
476
+ x: groups[group].x,
477
+ y: groups[group].y,
478
+ z: groups[group].z,
479
+ text: groups[group].text,
480
+ name: group,
481
+ type: plotType,
482
+ mode: plotType === 'scatter' ? 'markers' : 'lines',
483
+ marker: {
484
+ size: plotType === 'scatter' ? pointSize : undefined,
485
+ color: colorScale[colorIndex],
486
+ opacity: opacity
487
+ },
488
+ line: plotType !== 'scatter' ? {
489
+ color: colorScale[colorIndex],
490
+ width: pointSize / 2
491
+ } : undefined,
492
+ hoverinfo: 'text'
493
+ };
494
+ traces.push(trace);
495
+ });
496
+ } else {
497
+ // Single trace with all data
498
+ const x = currentData.map(row => row[xAxis]);
499
+ const y = currentData.map(row => row[yAxis]);
500
+ const z = currentData.map(row => row[zAxis]);
501
+ const text = currentData.map(row => Object.entries(row).map(([key, val]) => `${key}: ${val}`).join('<br>'));
502
+
503
+ const trace = {
504
+ x: x,
505
+ y: y,
506
+ z: z,
507
+ text: text,
508
+ type: plotType,
509
+ mode: plotType === 'scatter' ? 'markers' : 'lines',
510
+ marker: {
511
+ size: plotType === 'scatter' ? pointSize : undefined,
512
+ color: colorScale[0],
513
+ opacity: opacity
514
+ },
515
+ line: plotType !== 'scatter' ? {
516
+ color: colorScale[0],
517
+ width: pointSize / 2
518
+ } : undefined,
519
+ hoverinfo: 'text'
520
+ };
521
+ traces.push(trace);
522
+ }
523
+
524
+ // Layout configuration with ggplot2-inspired styling
525
+ const layout = {
526
+ title: '3D Visualization',
527
+ scene: {
528
+ xaxis: { title: xAxis, gridcolor: 'rgb(200, 200, 200)', backgroundcolor: 'rgb(240, 240, 240)' },
529
+ yaxis: { title: yAxis, gridcolor: 'rgb(200, 200, 200)', backgroundcolor: 'rgb(240, 240, 240)' },
530
+ zaxis: { title: zAxis, gridcolor: 'rgb(200, 200, 200)', backgroundcolor: 'rgb(240, 240, 240)' },
531
+ bgcolor: 'rgb(255, 255, 255)'
532
+ },
533
+ margin: { l: 0, r: 0, b: 0, t: 30 },
534
+ paper_bgcolor: 'rgba(0,0,0,0)',
535
+ plot_bgcolor: 'rgba(0,0,0,0)',
536
+ legend: {
537
+ bgcolor: 'rgba(255, 255, 255, 0.8)',
538
+ bordercolor: 'rgba(0, 0, 0, 0.2)',
539
+ borderwidth: 1
540
+ }
541
+ };
542
+
543
+ Plotly.newPlot('3d-plot', traces, layout, { responsive: true });
544
+ }
545
+
546
+ // Export functions
547
+ function exportPNG() {
548
+ Plotly.downloadImage('3d-plot', {
549
+ format: 'png',
550
+ width: 1200,
551
+ height: 800,
552
+ filename: '3d-ggplot-plot'
553
+ });
554
+ }
555
+
556
+ function exportSVG() {
557
+ Plotly.downloadImage('3d-plot', {
558
+ format: 'svg',
559
+ width: 1200,
560
+ height: 800,
561
+ filename: '3d-ggplot-plot'
562
+ });
563
+ }
564
+ </script>
565
+ <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=guillermo2323/ggplotgrahs-like-app" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
566
+ </html>