mirror of
https://github.com/gradio-app/gradio.git
synced 2024-12-21 02:19:59 +08:00
timeseries commit
This commit is contained in:
parent
0d5057f6b8
commit
3bfeb4105f
23
demo/fraud_detector.py
Normal file
23
demo/fraud_detector.py
Normal file
@ -0,0 +1,23 @@
|
||||
import gradio as gr
|
||||
import pandas as pd
|
||||
import random
|
||||
|
||||
def fraud_detector(card_activity, categories, sensitivity):
|
||||
activity_range = random.randint(0, 100)
|
||||
return {"fraud": activity_range / 100., "not fraud": 1 - activity_range / 100.}
|
||||
|
||||
iface = gr.Interface(fraud_detector,
|
||||
[
|
||||
gr.inputs.Timeseries(
|
||||
x="time",
|
||||
y=["retail", "food", "other"]
|
||||
),
|
||||
gr.inputs.CheckboxGroup(["retail", "food", "other"], default=["retail", "food", "other"]),
|
||||
gr.inputs.Slider(1,3)
|
||||
],
|
||||
[
|
||||
gr.outputs.Label(label="Fraud Level"),
|
||||
]
|
||||
)
|
||||
if __name__ == "__main__":
|
||||
iface.launch()
|
5923
frontend/package-lock.json
generated
5923
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -14,9 +14,11 @@
|
||||
"fabric": "^4.5.0",
|
||||
"html2canvas-objectfit-fix": "^1.2.0",
|
||||
"jspreadsheet-ce": "^4.7.3",
|
||||
"plotly.js": "^2.3.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-json-tree": "^0.15.0",
|
||||
"react-plotly.js": "^2.5.1",
|
||||
"react-scripts": "4.0.3",
|
||||
"react-webcam": "^5.2.3",
|
||||
"sass": "^1.32.8",
|
||||
|
@ -9,6 +9,7 @@ import { NumberInput, NumberInputExample } from './interfaces/input/number';
|
||||
import { RadioInput, RadioInputExample } from './interfaces/input/radio';
|
||||
import { SliderInput, SliderInputExample } from './interfaces/input/slider';
|
||||
import { TextboxInput, TextboxInputExample } from './interfaces/input/textbox';
|
||||
import { TimeseriesInput, TimeseriesInputExample } from './interfaces/input/timeseries';
|
||||
import { VideoInput, VideoInputExample } from './interfaces/input/video';
|
||||
|
||||
import { AudioOutput, AudioOutputExample } from './interfaces/output/audio';
|
||||
@ -36,6 +37,7 @@ let input_component_map = {
|
||||
"radio": [RadioInput, RadioInputExample],
|
||||
"slider": [SliderInput, SliderInputExample],
|
||||
"textbox": [TextboxInput, TextboxInputExample],
|
||||
"timeseries": [TimeseriesInput, TimeseriesInputExample],
|
||||
"video": [VideoInput, VideoInputExample],
|
||||
}
|
||||
let output_component_map = {
|
||||
|
121
frontend/src/interfaces/input/timeseries.jsx
Normal file
121
frontend/src/interfaces/input/timeseries.jsx
Normal file
@ -0,0 +1,121 @@
|
||||
import React from 'react';
|
||||
import ComponentExample from '../component_example';
|
||||
import { CSVToArray } from '../../utils';
|
||||
import Plot from 'react-plotly.js';
|
||||
|
||||
class TimeseriesInput extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
this.uploader = React.createRef();
|
||||
this.openFileUpload = this.openFileUpload.bind(this);
|
||||
this.load_preview_from_files = this.load_preview_from_files.bind(this);
|
||||
this.load_preview_from_upload = this.load_preview_from_upload.bind(this);
|
||||
this.load_preview_from_drop = this.load_preview_from_drop.bind(this);
|
||||
}
|
||||
handleChange(data) {
|
||||
this.props.handleChange(data);
|
||||
}
|
||||
openFileUpload() {
|
||||
this.uploader.current.click();
|
||||
}
|
||||
render() {
|
||||
let no_action = (evt) => {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
}
|
||||
if (this.props.value !== null) {
|
||||
let file = this.props.value[0];
|
||||
return (
|
||||
<div className="input_timeseries">
|
||||
<Plot
|
||||
data={this.state.y_indices.map((y_index, i) => {
|
||||
return {
|
||||
x: this.props.value["data"].map(row => row[this.state.x_index]),
|
||||
y: this.props.value["data"].map(row => row[y_index]),
|
||||
type: 'line',
|
||||
name: this.props.y[i]
|
||||
}
|
||||
})}
|
||||
layout={{
|
||||
width: 480,
|
||||
height: 320,
|
||||
title: {text: "Card Activity"},
|
||||
xAxis: {title: {text: "Day"}},
|
||||
yAxis: {title: {text: "Spend"}},
|
||||
}}
|
||||
/>
|
||||
</div>)
|
||||
} else {
|
||||
return (
|
||||
<div className="input_timeseries" onDrag={no_action} onDragStart={no_action} onDragEnd={no_action} onDragOver={no_action} onDragEnter={no_action} onDragLeave={no_action} onDrop={no_action} >
|
||||
<div className="upload_zone" onClick={this.openFileUpload} onDrop={this.load_preview_from_drop}>
|
||||
Upload Timeseries CSV
|
||||
{this.props.x !== null ? <>
|
||||
<br />
|
||||
X Column: {this.props.x}
|
||||
<br />
|
||||
Y Column: {this.props.y.join(", ")}
|
||||
</> : false}
|
||||
</div>
|
||||
<input className="hidden_upload" type="file" multiple={this.props.file_count === "multiple"} webkitdirectory={this.props.file_count === "directory"} mozdirectory={this.props.file_count === "directory"} ref={this.uploader} onChange={this.load_preview_from_upload} style={{ display: "none" }} />
|
||||
</div>)
|
||||
}
|
||||
}
|
||||
load_preview_from_drop(evt) {
|
||||
this.load_preview_from_files(evt.dataTransfer.files)
|
||||
}
|
||||
load_preview_from_upload(evt) {
|
||||
this.load_preview_from_files(evt.target.files);
|
||||
}
|
||||
load_file(reader) {
|
||||
let lines = reader.result;
|
||||
let headers = null;
|
||||
let data = null;
|
||||
if (lines && lines.length > 0) {
|
||||
let line_array = CSVToArray(lines);
|
||||
if (line_array.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (this.props.x === null) {
|
||||
this.setState({ "x_index": 0, "y_indices": [1] })
|
||||
data = line_array;
|
||||
} else {
|
||||
let x_index = line_array[0].indexOf(this.props.x);
|
||||
let y_indices = this.props.y.map(y_col => line_array[0].indexOf(y_col));
|
||||
if (x_index === -1) {
|
||||
alert("Missing x column: " + this.props.x);
|
||||
return;
|
||||
}
|
||||
if (y_indices.includes(-1)) {
|
||||
alert("Missing y column: " + this.props.y[y_indices.indexOf(-1)]);
|
||||
return;
|
||||
}
|
||||
this.setState({ "x_index": x_index, "y_indices": y_indices })
|
||||
headers = line_array[0];
|
||||
data = line_array.slice(1);
|
||||
}
|
||||
this.handleChange({ "headers": headers, "data": data });
|
||||
}
|
||||
}
|
||||
load_preview_from_files(files) {
|
||||
if (!files.length || !window.FileReader) {
|
||||
return;
|
||||
}
|
||||
this.file_data = [];
|
||||
for (let file of files) {
|
||||
let ReaderObj = new FileReader()
|
||||
ReaderObj.readAsBinaryString(file)
|
||||
ReaderObj.onloadend = this.load_file.bind(this, ReaderObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TimeseriesInputExample extends ComponentExample {
|
||||
render() {
|
||||
return <div className="input_file_example">{this.props.value}</div>
|
||||
}
|
||||
}
|
||||
|
||||
export { TimeseriesInput, TimeseriesInputExample };
|
@ -388,6 +388,18 @@
|
||||
@apply text-2xl p-2;
|
||||
}
|
||||
}
|
||||
.input_timeseries {
|
||||
@apply w-full h-96;
|
||||
.upload_zone {
|
||||
@apply border-8 border-gray-300 border-dashed w-full h-full flex justify-center items-center text-3xl text-gray-400 text-center cursor-pointer leading-10;
|
||||
}
|
||||
.file_preview_holder {
|
||||
@apply w-full h-full flex flex-col justify-center items-center relative inline-block;
|
||||
}
|
||||
.js-plotly-plot, .plotly.js-plotly-plot * {
|
||||
position: static !important;
|
||||
}
|
||||
}
|
||||
/* Output Components */
|
||||
.output_text {
|
||||
word-break: break-word;
|
||||
|
@ -107,3 +107,31 @@ export function array_compare(a1, a2) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function CSVToArray(strData, strDelimiter) {
|
||||
strDelimiter = (strDelimiter || ",");
|
||||
let objPattern = new RegExp(
|
||||
(
|
||||
"(\\" + strDelimiter + "|\\r?\\n|\\r|^)" +
|
||||
"(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" +
|
||||
"([^\"\\" + strDelimiter + "\\r\\n]*))"
|
||||
),
|
||||
"gi"
|
||||
);
|
||||
let arrData = [[]];
|
||||
let arrMatches = null;
|
||||
while (arrMatches = objPattern.exec(strData)) {
|
||||
let strMatchedDelimiter = arrMatches[1];
|
||||
let strMatchedValue = [];
|
||||
if (strMatchedDelimiter.length && (strMatchedDelimiter != strDelimiter)) {
|
||||
arrData.push([]);
|
||||
}
|
||||
if (arrMatches[2]) {
|
||||
strMatchedValue = arrMatches[2].replace(new RegExp("\"\"", "g"), "\"");
|
||||
} else {
|
||||
strMatchedValue = arrMatches[3];
|
||||
}
|
||||
arrData[arrData.length - 1].push(strMatchedValue);
|
||||
}
|
||||
return (arrData);
|
||||
}
|
||||
|
@ -32,6 +32,8 @@ gradio/frontend/static/bundle.css.map
|
||||
gradio/frontend/static/bundle.js
|
||||
gradio/frontend/static/bundle.js.LICENSE.txt
|
||||
gradio/frontend/static/bundle.js.map
|
||||
gradio/frontend/static/css/main.2056a447.css
|
||||
gradio/frontend/static/css/main.2056a447.css.map
|
||||
gradio/frontend/static/css/main.337638fd.css
|
||||
gradio/frontend/static/css/main.337638fd.css.map
|
||||
gradio/frontend/static/css/main.347bef8c.css
|
||||
@ -42,6 +44,8 @@ gradio/frontend/static/css/main.bc3b604e.css
|
||||
gradio/frontend/static/css/main.bc3b604e.css.map
|
||||
gradio/frontend/static/css/main.c7572f0f.css
|
||||
gradio/frontend/static/css/main.c7572f0f.css.map
|
||||
gradio/frontend/static/css/main.c770ef42.css
|
||||
gradio/frontend/static/css/main.c770ef42.css.map
|
||||
gradio/frontend/static/media/logo_loading.e93acd82.jpg
|
||||
test/test_demos.py
|
||||
test/test_inputs.py
|
||||
|
@ -1,15 +1,15 @@
|
||||
numpy
|
||||
scipy
|
||||
matplotlib
|
||||
pandas
|
||||
pillow
|
||||
Flask-Cors>=3.0.8
|
||||
Flask-Login
|
||||
Flask>=1.1.1
|
||||
analytics-python
|
||||
ffmpy
|
||||
flask-cachebuster
|
||||
markdown2
|
||||
matplotlib
|
||||
numpy
|
||||
pandas
|
||||
paramiko
|
||||
pillow
|
||||
pycryptodome
|
||||
requests
|
||||
paramiko
|
||||
analytics-python
|
||||
Flask>=1.1.1
|
||||
Flask-Cors>=3.0.8
|
||||
flask-cachebuster
|
||||
Flask-Login
|
||||
scipy
|
||||
|
@ -1,17 +1,17 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "/static/css/main.337638fd.css",
|
||||
"main.css": "/static/css/main.c770ef42.css",
|
||||
"main.js": "/static/bundle.js",
|
||||
"main.js.map": "/static/bundle.js.map",
|
||||
"index.html": "/index.html",
|
||||
"static/bundle.css.map": "/static/bundle.css.map",
|
||||
"static/bundle.js.LICENSE.txt": "/static/bundle.js.LICENSE.txt",
|
||||
"static/css/main.337638fd.css.map": "/static/css/main.337638fd.css.map",
|
||||
"static/css/main.c770ef42.css.map": "/static/css/main.c770ef42.css.map",
|
||||
"static/media/logo_loading.e93acd82.jpg": "/static/media/logo_loading.e93acd82.jpg"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/bundle.css",
|
||||
"static/css/main.337638fd.css",
|
||||
"static/css/main.c770ef42.css",
|
||||
"static/bundle.js"
|
||||
]
|
||||
}
|
@ -8,4 +8,4 @@
|
||||
window.config = {{ config|tojson }};
|
||||
} catch (e) {
|
||||
window.config = {};
|
||||
}</script><script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.1/iframeResizer.contentWindow.min.js"></script><title>Gradio</title><link href="static/bundle.css" rel="stylesheet"><link href="static/css/main.337638fd.css" rel="stylesheet"></head><body><div id="root"></div><script src="static/bundle.js"></script></body></html>
|
||||
}</script><script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.1/iframeResizer.contentWindow.min.js"></script><title>Gradio</title><link href="static/bundle.css" rel="stylesheet"><link href="static/css/main.c770ef42.css" rel="stylesheet"></head><body><div id="root"></div><script src="static/bundle.js"></script></body></html>
|
@ -1143,35 +1143,55 @@ class Dataframe(InputComponent):
|
||||
else:
|
||||
raise ValueError("Unknown type: " + str(self.type) + ". Please choose from: 'pandas', 'numpy', 'array'.")
|
||||
|
||||
# def set_interpret_parameters(self):
|
||||
# """
|
||||
# Calculates interpretation score of each cell in the Dataframe by using a "leave one out" method to calculate the score of each cell by removing the cell and measuring the delta of the output value.
|
||||
# """
|
||||
# return self
|
||||
|
||||
# def get_interpretation_neighbors(self, x):
|
||||
# x = pd.DataFrame(x)
|
||||
# leave_one_out_sets = []
|
||||
# shape = x.shape
|
||||
# for i in range(shape[0]):
|
||||
# for j in range(shape[1]):
|
||||
# scalar = x.iloc[i, j]
|
||||
# leave_one_out_df = x.copy()
|
||||
# if is_bool_dtype(scalar):
|
||||
# leave_one_out_df.iloc[i, j] = not scalar
|
||||
# elif is_numeric_dtype(scalar):
|
||||
# leave_one_out_df.iloc[i, j] = 0
|
||||
# elif is_string_dtype(scalar):
|
||||
# leave_one_out_df.iloc[i, j] = ""
|
||||
# leave_one_out_sets.append(leave_one_out_df.values.tolist())
|
||||
# return leave_one_out_sets, {"shape": x.shape}
|
||||
def embed(self, x):
|
||||
raise NotImplementedError("DataFrame doesn't currently support embeddings")
|
||||
|
||||
def save_flagged(self, dir, label, data, encryption_key):
|
||||
"""
|
||||
Returns: (List[List[Union[str, float]]]) 2D array
|
||||
"""
|
||||
return json.dumps(data)
|
||||
|
||||
def restore_flagged(self, data):
|
||||
return json.loads(data)
|
||||
|
||||
|
||||
class Timeseries(InputComponent):
|
||||
"""
|
||||
Component accepts pandas.DataFrame uploaded as a timeseries csv file.
|
||||
Input type: pandas.DataFrame
|
||||
"""
|
||||
|
||||
def __init__(self, x=None, y=None, label=None):
|
||||
"""
|
||||
Parameters:
|
||||
x (str): Column name of x (time) series. None if csv has no headers, in which case first column is x series.
|
||||
y (Union[str, List[str]]): Column name of y series, or list of column names if multiple series. None if csv has no headers, in which case every column after first is a y series.
|
||||
label (str): component name in interface.
|
||||
"""
|
||||
self.x = x
|
||||
if isinstance(y, str):
|
||||
y = [y]
|
||||
self.y = y
|
||||
super().__init__(label)
|
||||
|
||||
def get_template_context(self):
|
||||
return {
|
||||
"x": self.x,
|
||||
"y": self.y,
|
||||
**super().get_template_context()
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def get_shortcut_implementations(cls):
|
||||
return {
|
||||
"timeseries": {},
|
||||
}
|
||||
|
||||
def preprocess(self, x):
|
||||
return pd.DataFrame(data=x["data"], columns=x["headers"])
|
||||
|
||||
# def get_interpretation_scores(self, x, neighbors, scores, shape):
|
||||
# """
|
||||
# Returns:
|
||||
# (List[List[float]]): A 2D array where each value corrseponds to the interpretation score of each cell.
|
||||
# """
|
||||
# return np.array(scores).reshape((shape)).tolist()
|
||||
|
||||
def embed(self, x):
|
||||
raise NotImplementedError("DataFrame doesn't currently support embeddings")
|
||||
|
Loading…
Reference in New Issue
Block a user