visidata 2.11.1__py3-none-any.whl → 3.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- visidata/__init__.py +72 -91
- visidata/_input.py +259 -42
- visidata/_open.py +84 -29
- visidata/_types.py +21 -3
- visidata/_urlcache.py +17 -4
- visidata/aggregators.py +78 -25
- visidata/apps/__init__.py +0 -0
- visidata/apps/vdsql/__about__.py +8 -0
- visidata/apps/vdsql/__init__.py +5 -0
- visidata/apps/vdsql/__main__.py +27 -0
- visidata/apps/vdsql/_ibis.py +748 -0
- visidata/apps/vdsql/bigquery.py +61 -0
- visidata/apps/vdsql/clickhouse.py +53 -0
- visidata/apps/vdsql/setup.py +40 -0
- visidata/apps/vdsql/snowflake.py +67 -0
- visidata/apps/vgit/__init__.py +13 -0
- {vgit → visidata/apps/vgit}/blame.py +5 -2
- {vgit → visidata/apps/vgit}/branch.py +31 -16
- {vgit → visidata/apps/vgit}/config.py +3 -3
- visidata/apps/vgit/diff.py +169 -0
- visidata/apps/vgit/gitsheet.py +161 -0
- {vgit → visidata/apps/vgit}/grep.py +6 -5
- visidata/apps/vgit/log.py +81 -0
- {vgit → visidata/apps/vgit}/main.py +18 -5
- {vgit → visidata/apps/vgit}/remote.py +8 -4
- visidata/apps/vgit/repos.py +71 -0
- {vgit → visidata/apps/vgit}/setup.py +6 -4
- visidata/apps/vgit/stash.py +69 -0
- visidata/apps/vgit/status.py +204 -0
- {vgit → visidata/apps/vgit}/statusbar.py +2 -0
- visidata/basesheet.py +63 -51
- visidata/canvas.py +208 -93
- visidata/choose.py +6 -6
- visidata/clean_names.py +29 -0
- visidata/clipboard.py +73 -17
- visidata/cliptext.py +220 -46
- visidata/cmdlog.py +88 -114
- visidata/color.py +142 -56
- visidata/column.py +121 -129
- visidata/ddw/input.ddw +74 -79
- visidata/ddw/regex.ddw +57 -0
- visidata/ddwplay.py +33 -14
- visidata/deprecated.py +77 -3
- visidata/desktop/visidata.desktop +7 -0
- visidata/editor.py +12 -6
- visidata/errors.py +6 -2
- visidata/experimental/__init__.py +0 -0
- visidata/experimental/diff_sheet.py +29 -0
- visidata/experimental/digit_autoedit.py +6 -0
- visidata/experimental/gdrive.py +89 -0
- visidata/experimental/google.py +37 -0
- visidata/experimental/gsheets.py +79 -0
- visidata/experimental/live_search.py +37 -0
- visidata/experimental/liveupdate.py +45 -0
- visidata/experimental/mark.py +133 -0
- visidata/experimental/noahs_tapestry/__init__.py +1 -0
- visidata/experimental/noahs_tapestry/tapestry.py +147 -0
- visidata/experimental/rownum.py +73 -0
- visidata/experimental/slide_cells.py +26 -0
- visidata/expr.py +8 -4
- visidata/extensible.py +22 -4
- visidata/features/__init__.py +0 -0
- visidata/features/addcol_audiometadata.py +42 -0
- visidata/features/addcol_histogram.py +34 -0
- visidata/features/canvas_save_svg.py +69 -0
- visidata/features/change_precision.py +46 -0
- visidata/features/cmdpalette.py +197 -0
- visidata/features/colorbrewer.py +363 -0
- visidata/{colorsheet.py → features/colorsheet.py} +17 -16
- visidata/features/command_server.py +105 -0
- visidata/features/currency_to_usd.py +70 -0
- visidata/{customdate.py → features/customdate.py} +2 -0
- visidata/features/dedupe.py +132 -0
- visidata/{describe.py → features/describe.py} +17 -15
- visidata/features/errors_guide.py +26 -0
- visidata/features/expand_cols.py +202 -0
- visidata/{fill.py → features/fill.py} +3 -1
- visidata/{freeze.py → features/freeze.py} +11 -6
- visidata/features/graph_seaborn.py +79 -0
- visidata/features/helloworld.py +10 -0
- visidata/features/hint_types.py +17 -0
- visidata/{incr.py → features/incr.py} +5 -0
- visidata/{join.py → features/join.py} +107 -53
- visidata/features/known_cols.py +21 -0
- visidata/features/layout.py +62 -0
- visidata/{melt.py → features/melt.py} +32 -21
- visidata/features/normcol.py +118 -0
- visidata/features/open_config.py +7 -0
- visidata/features/open_syspaste.py +18 -0
- visidata/features/ping.py +157 -0
- visidata/features/procmgr.py +208 -0
- visidata/features/random_sample.py +6 -0
- visidata/{regex.py → features/regex.py} +47 -31
- visidata/features/reload_every.py +55 -0
- visidata/features/rename_col_cascade.py +30 -0
- visidata/features/scroll_context.py +60 -0
- visidata/features/select_equal_selected.py +11 -0
- visidata/features/setcol_fake.py +65 -0
- visidata/{slide.py → features/slide.py} +77 -21
- visidata/features/sparkline.py +48 -0
- visidata/features/status_source.py +20 -0
- visidata/{sysedit.py → features/sysedit.py} +2 -1
- visidata/features/sysopen_mailcap.py +46 -0
- visidata/features/term_extras.py +13 -0
- visidata/{transpose.py → features/transpose.py} +5 -4
- visidata/features/type_ipaddr.py +73 -0
- visidata/features/type_url.py +11 -0
- visidata/{unfurl.py → features/unfurl.py} +9 -9
- visidata/{window.py → features/window.py} +2 -2
- visidata/form.py +50 -21
- visidata/freqtbl.py +81 -33
- visidata/fuzzymatch.py +414 -0
- visidata/graph.py +105 -33
- visidata/guide.py +200 -0
- visidata/help.py +75 -44
- visidata/hint.py +39 -0
- visidata/indexsheet.py +109 -0
- visidata/input_history.py +55 -0
- visidata/interface.py +58 -0
- visidata/keys.py +20 -16
- visidata/loaders/__init__.py +9 -0
- visidata/loaders/_pandas.py +61 -21
- visidata/loaders/api_airtable.py +70 -0
- visidata/loaders/api_bitio.py +102 -0
- visidata/loaders/api_matrix.py +148 -0
- visidata/loaders/api_reddit.py +306 -0
- visidata/loaders/api_zulip.py +249 -0
- visidata/loaders/archive.py +41 -7
- visidata/loaders/arrow.py +7 -7
- visidata/loaders/conll.py +49 -0
- visidata/loaders/csv.py +25 -7
- visidata/loaders/eml.py +3 -4
- visidata/loaders/f5log.py +1204 -0
- visidata/loaders/fec.py +325 -0
- visidata/loaders/fixed_width.py +2 -4
- visidata/loaders/frictionless.py +3 -3
- visidata/loaders/geojson.py +8 -5
- visidata/loaders/google.py +48 -0
- visidata/loaders/graphviz.py +4 -4
- visidata/loaders/hdf5.py +4 -4
- visidata/loaders/html.py +54 -12
- visidata/loaders/http.py +84 -30
- visidata/loaders/imap.py +20 -10
- visidata/loaders/jrnl.py +52 -0
- visidata/loaders/json.py +83 -29
- visidata/loaders/jsonla.py +74 -0
- visidata/loaders/lsv.py +15 -11
- visidata/loaders/mailbox.py +40 -0
- visidata/loaders/markdown.py +1 -3
- visidata/loaders/mbtiles.py +4 -5
- visidata/loaders/mysql.py +11 -13
- visidata/loaders/npy.py +7 -7
- visidata/loaders/odf.py +4 -1
- visidata/loaders/orgmode.py +428 -0
- visidata/loaders/pandas_freqtbl.py +14 -20
- visidata/loaders/parquet.py +62 -6
- visidata/loaders/pcap.py +3 -3
- visidata/loaders/pdf.py +4 -3
- visidata/loaders/png.py +19 -13
- visidata/loaders/postgres.py +9 -8
- visidata/loaders/rec.py +7 -3
- visidata/loaders/s3.py +342 -0
- visidata/loaders/sas.py +5 -5
- visidata/loaders/scrape.py +186 -0
- visidata/loaders/shp.py +6 -5
- visidata/loaders/spss.py +5 -6
- visidata/loaders/sqlite.py +68 -28
- visidata/loaders/texttables.py +1 -1
- visidata/loaders/toml.py +60 -0
- visidata/loaders/tsv.py +61 -19
- visidata/loaders/ttf.py +19 -7
- visidata/loaders/unzip_http.py +6 -5
- visidata/loaders/usv.py +1 -1
- visidata/loaders/vcf.py +16 -16
- visidata/loaders/vds.py +10 -7
- visidata/loaders/vdx.py +30 -5
- visidata/loaders/xlsb.py +8 -1
- visidata/loaders/xlsx.py +145 -25
- visidata/loaders/xml.py +6 -3
- visidata/loaders/xword.py +4 -4
- visidata/loaders/yaml.py +15 -5
- visidata/macros.py +129 -42
- visidata/main.py +119 -94
- visidata/mainloop.py +101 -155
- visidata/man/parse_options.py +2 -2
- visidata/man/vd.1 +302 -149
- visidata/man/vd.txt +291 -154
- visidata/memory.py +3 -3
- visidata/menu.py +104 -423
- visidata/metasheets.py +59 -141
- visidata/modify.py +78 -23
- visidata/motd.py +3 -3
- visidata/mouse.py +137 -0
- visidata/movement.py +43 -35
- visidata/optionssheet.py +99 -0
- visidata/path.py +113 -32
- visidata/pivot.py +73 -47
- visidata/plugins.py +65 -192
- visidata/pyobj.py +55 -205
- visidata/rename_col.py +20 -0
- visidata/save.py +37 -20
- visidata/search.py +54 -10
- visidata/selection.py +84 -5
- visidata/settings.py +162 -25
- visidata/sheets.py +239 -260
- visidata/shell.py +51 -21
- visidata/sidebar.py +162 -0
- visidata/sort.py +11 -4
- visidata/statusbar.py +114 -104
- visidata/stored_list.py +43 -0
- visidata/stored_prop.py +38 -0
- visidata/tests/benchmark.csv +52 -0
- visidata/tests/conftest.py +3 -3
- visidata/tests/test_cliptext.py +39 -0
- visidata/tests/test_commands.py +65 -7
- visidata/tests/test_edittext.py +2 -2
- visidata/tests/test_features.py +28 -0
- visidata/tests/test_menu.py +14 -0
- visidata/tests/test_path.py +13 -4
- visidata/text_source.py +53 -0
- visidata/textsheet.py +10 -3
- visidata/theme.py +44 -0
- visidata/themes/__init__.py +0 -0
- visidata/themes/ascii8.py +84 -0
- visidata/themes/asciimono.py +84 -0
- visidata/themes/light.py +17 -0
- visidata/threads.py +89 -40
- visidata/tuiwin.py +22 -0
- visidata/type_currency.py +22 -3
- visidata/type_date.py +31 -9
- visidata/type_floatsi.py +5 -1
- visidata/undo.py +17 -5
- visidata/utils.py +106 -23
- visidata/vdobj.py +28 -17
- visidata/windows.py +10 -0
- visidata/wrappers.py +9 -3
- visidata-3.0.1.data/data/share/applications/visidata.desktop +7 -0
- {visidata-2.11.1.data → visidata-3.0.1.data}/data/share/man/man1/vd.1 +302 -149
- {visidata-2.11.1.data → visidata-3.0.1.data}/data/share/man/man1/visidata.1 +302 -149
- visidata-3.0.1.data/scripts/vd2to3.vdx +9 -0
- {visidata-2.11.1.dist-info → visidata-3.0.1.dist-info}/METADATA +12 -8
- visidata-3.0.1.dist-info/RECORD +258 -0
- {visidata-2.11.1.dist-info → visidata-3.0.1.dist-info}/WHEEL +1 -1
- vgit/__init__.py +0 -1
- vgit/gitsheet.py +0 -164
- visidata/layout.py +0 -44
- visidata/misc.py +0 -5
- visidata-2.11.1.data/scripts/vgit +0 -9
- visidata-2.11.1.dist-info/RECORD +0 -155
- {vgit → visidata/apps/vgit}/__main__.py +0 -0
- {vgit → visidata/apps/vgit}/abort.py +0 -0
- /visidata/{repeat.py → features/repeat.py} +0 -0
- {visidata-2.11.1.data → visidata-3.0.1.data}/scripts/vd +0 -0
- {visidata-2.11.1.dist-info → visidata-3.0.1.dist-info}/LICENSE.gpl3 +0 -0
- {visidata-2.11.1.dist-info → visidata-3.0.1.dist-info}/entry_points.txt +0 -0
- {visidata-2.11.1.dist-info → visidata-3.0.1.dist-info}/top_level.txt +0 -0
visidata/form.py
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
import functools
|
2
|
-
from visidata import clipdraw, colors, BaseSheet, VisiData, VisiDataMetaSheet, vd, EscapeException, AttrDict, ENTER
|
2
|
+
from visidata import clipdraw, colors, BaseSheet, VisiData, VisiDataMetaSheet, vd, EscapeException, AttrDict, ENTER, dispwidth, AcceptInput
|
3
3
|
|
4
4
|
|
5
5
|
@VisiData.api
|
6
6
|
def open_mnu(vd, p):
|
7
|
-
return FormSheet(p.
|
7
|
+
return FormSheet(p.base_stem, source=p)
|
8
8
|
|
9
9
|
|
10
10
|
vd.save_mnu=vd.save_tsv
|
11
11
|
|
12
12
|
class FormSheet(VisiDataMetaSheet):
|
13
|
-
rowtype='labels' # rowdef: { .x .y .text .color .command .input .
|
13
|
+
rowtype='labels' # rowdef: { .x .y .text .color .command .input .key}
|
14
14
|
|
15
15
|
@VisiData.api
|
16
16
|
def replayCommand(vd, longname, sheet=None, col='', row=''):
|
@@ -18,9 +18,16 @@ def replayCommand(vd, longname, sheet=None, col='', row=''):
|
|
18
18
|
|
19
19
|
|
20
20
|
class FormCanvas(BaseSheet):
|
21
|
-
rowtype='labels'
|
22
|
-
|
23
|
-
|
21
|
+
rowtype = 'labels'
|
22
|
+
pressedLabel = None
|
23
|
+
|
24
|
+
def onPressed(self, r):
|
25
|
+
if r.key:
|
26
|
+
self.pressedLabel = r
|
27
|
+
|
28
|
+
def onReleased(self, r):
|
29
|
+
if self.pressedLabel is r:
|
30
|
+
raise AcceptInput(r.key)
|
24
31
|
|
25
32
|
def reload(self):
|
26
33
|
self.rows = self.source.rows
|
@@ -38,12 +45,17 @@ class FormCanvas(BaseSheet):
|
|
38
45
|
y = int(y)
|
39
46
|
if y < 0: y += h
|
40
47
|
if x < 0: x += w
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
48
|
+
color = r.color
|
49
|
+
if r is self.pressedLabel:
|
50
|
+
color += ' reverse'
|
51
|
+
clipdraw(scr, y, x, r.text, colors[color])
|
52
|
+
# underline first occurrence of r.key in r.text
|
53
|
+
if hasattr(r, 'key') and r.key:
|
54
|
+
index = r.text.find(r.key)
|
55
|
+
clipdraw(scr, y, x+index, r.text[index:len(r.key)+1], colors[color + " underline"])
|
56
|
+
vd.onMouse(scr, x, y, dispwidth(r.text), 1,
|
57
|
+
BUTTON1_PRESSED=lambda y,x,key,r=r,sheet=self: sheet.onPressed(r),
|
58
|
+
BUTTON1_RELEASED=lambda y,x,key,r=r,sheet=self: sheet.onReleased(r))
|
47
59
|
|
48
60
|
def run(self, scr):
|
49
61
|
vd.setWindows(vd.scrFull)
|
@@ -53,35 +65,52 @@ class FormCanvas(BaseSheet):
|
|
53
65
|
maxh = max(int(r.y) for r in drawnrows)
|
54
66
|
h, w = vd.scrFull.getmaxyx()
|
55
67
|
y, x = max(0, (h-maxh)//2-1), max(0, (w-maxw)//2-1)
|
56
|
-
self.scrForm = vd.scrFull
|
68
|
+
self.scrForm = vd.subwindow(vd.scrFull, x, y, min(w-1, maxw+1), min(h-1, maxh+2))
|
57
69
|
self.scrForm.keypad(1)
|
58
70
|
curinput = inputs[0] if inputs else None
|
59
|
-
|
60
|
-
vd.draw_all()
|
71
|
+
vd.draw_all()
|
61
72
|
|
62
|
-
|
63
|
-
|
64
|
-
|
73
|
+
self.scrForm.erase()
|
74
|
+
self.scrForm.border()
|
75
|
+
self.draw(self.scrForm)
|
65
76
|
|
77
|
+
while True:
|
66
78
|
k = vd.getkeystroke(self.scrForm, self)
|
67
79
|
if k in ['^C', '^Q', '^[', 'q']:
|
68
80
|
return {}
|
69
81
|
if curinput and k in curinput.keystrokes:
|
70
82
|
return {curinput.input: k}
|
83
|
+
if k == 'KEY_MOUSE':
|
84
|
+
r = vd.parseMouse(form=self.scrForm)
|
85
|
+
if r.found:
|
86
|
+
f = vd.getMouse(r.x, r.y, r.keystroke)
|
87
|
+
if f:
|
88
|
+
try:
|
89
|
+
f(r.y, r.x, r.keystroke)
|
90
|
+
except AcceptInput as e:
|
91
|
+
return {curinput.input: e.args[0]}
|
92
|
+
except Exception as e:
|
93
|
+
vd.exceptionCaught(e)
|
94
|
+
break
|
95
|
+
|
96
|
+
if r.keystroke == 'BUTTON1_RELEASED':
|
97
|
+
self.pressedLabel = None
|
98
|
+
|
99
|
+
self.draw(self.scrForm)
|
71
100
|
|
72
101
|
|
73
102
|
@functools.wraps(VisiData.confirm)
|
74
103
|
@VisiData.api
|
75
104
|
def confirm(vd, prompt, exc=EscapeException):
|
76
105
|
'Display *prompt* on status line and demand input that starts with "Y" or "y" to proceed. Raise *exc* otherwise. Return True.'
|
77
|
-
if vd.options.batch:
|
106
|
+
if vd.options.batch and not vd.options.interactive:
|
78
107
|
return vd.fail('cannot confirm in batch mode: ' + prompt)
|
79
108
|
|
80
109
|
form = FormSheet('confirm', rows=[
|
81
110
|
AttrDict(x=2, y=0, text=' confirm ', color='yellow'),
|
82
111
|
AttrDict(x=2, y=1, text=prompt, color='yellow'),
|
83
|
-
AttrDict(x=.25, y=2, text=' yes ', color='black on yellow bold',
|
84
|
-
AttrDict(x=.75, y=2, text=' no ', color='black on yellow bold',
|
112
|
+
AttrDict(x=.25, y=2, text=' yes ', color='black on yellow bold', key='y'),
|
113
|
+
AttrDict(x=.75, y=2, text=' no ', color='black on yellow bold', key='n'),
|
85
114
|
AttrDict(input='yn', keystrokes=['y', 'n', ENTER]),
|
86
115
|
])
|
87
116
|
|
visidata/freqtbl.py
CHANGED
@@ -5,8 +5,7 @@ from visidata import vd, asyncthread, vlen, VisiData, Column, AttrColumn, Sheet,
|
|
5
5
|
from visidata.pivot import PivotSheet, PivotGroupRow
|
6
6
|
|
7
7
|
|
8
|
-
vd.
|
9
|
-
vd.option('disp_histolen', 50, 'width of histogram column')
|
8
|
+
vd.theme_option('disp_histogram', '■', 'histogram element character')
|
10
9
|
vd.option('histogram_bins', 0, 'number of bins for histogram of numeric columns')
|
11
10
|
vd.option('numeric_binning', False, 'bin numeric columns into ranges', replay=True)
|
12
11
|
|
@@ -14,7 +13,7 @@ vd.option('numeric_binning', False, 'bin numeric columns into ranges', replay=Tr
|
|
14
13
|
@VisiData.api
|
15
14
|
def valueNames(vd, discrete_vals, numeric_vals):
|
16
15
|
ret = [ '+'.join(str(x) for x in discrete_vals) ]
|
17
|
-
if numeric_vals != (0, 0):
|
16
|
+
if isinstance(numeric_vals, tuple) and numeric_vals != (0, 0):
|
18
17
|
ret.append('%s-%s' % numeric_vals)
|
19
18
|
|
20
19
|
return '+'.join(ret)
|
@@ -22,18 +21,37 @@ def valueNames(vd, discrete_vals, numeric_vals):
|
|
22
21
|
class HistogramColumn(Column):
|
23
22
|
def calcValue(col, row):
|
24
23
|
histogram = col.sheet.options.disp_histogram
|
25
|
-
histolen = col.
|
24
|
+
histolen = col.width-2
|
26
25
|
return histogram*(histolen*len(row.sourcerows)//col.sheet.largest)
|
27
26
|
|
28
27
|
|
28
|
+
def makeFreqTable(sheet, *groupByCols):
|
29
|
+
return FreqTableSheet(sheet.name,
|
30
|
+
'%s_freq' % '-'.join(col.name for col in groupByCols),
|
31
|
+
groupByCols=groupByCols,
|
32
|
+
source=sheet)
|
33
|
+
|
34
|
+
|
29
35
|
class FreqTableSheet(PivotSheet):
|
30
36
|
'Generate frequency-table sheet on currently selected column.'
|
37
|
+
guide = '''# Frequency Table
|
38
|
+
This is a *frequency analysis* of _{sheet.groupByColsName}_ from the *{sheet.groupByCols[0].sheet}* sheet.
|
39
|
+
|
40
|
+
Each row on this sheet corresponds to a *bin* of rows on the source sheet that have a distinct value. The _count_ and _percent_ columns show how many rows on the source sheet are in this bin.
|
41
|
+
|
42
|
+
- `Enter` to open a copy of the source sheet, with only the rows in the current bin.
|
43
|
+
- `g Enter` to open a copy of the source sheet, with a combination of the rows from all selected bins.
|
44
|
+
|
45
|
+
## Tips
|
46
|
+
|
47
|
+
- Use `+` on the source sheet, to add aggregators on other columns, and those metrics will appear as separate columns here.
|
48
|
+
- Selecting bins on this sheet will select those rows on the source sheet.
|
49
|
+
'''
|
31
50
|
rowtype = 'bins' # rowdef FreqRow(keys, sourcerows)
|
32
51
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
self.largest = 1
|
52
|
+
@property
|
53
|
+
def groupByColsName(self):
|
54
|
+
return '+'.join(c.name for c in self.groupByCols)
|
37
55
|
|
38
56
|
def selectRow(self, row):
|
39
57
|
self.source.select(row.sourcerows) # select all entries in the bin on the source sheet
|
@@ -46,10 +64,8 @@ class FreqTableSheet(PivotSheet):
|
|
46
64
|
def updateLargest(self, grouprow):
|
47
65
|
self.largest = max(self.largest, len(grouprow.sourcerows))
|
48
66
|
|
49
|
-
|
50
|
-
|
51
|
-
'Generate frequency table then reverse-sort by length.'
|
52
|
-
super().initCols()
|
67
|
+
def resetCols(self):
|
68
|
+
super().resetCols()
|
53
69
|
|
54
70
|
# add default bonus columns
|
55
71
|
for c in [
|
@@ -58,34 +74,39 @@ class FreqTableSheet(PivotSheet):
|
|
58
74
|
]:
|
59
75
|
self.addColumn(c)
|
60
76
|
|
61
|
-
if self.options.
|
62
|
-
c = HistogramColumn('histogram', type=str, width=self.options.
|
77
|
+
if self.options.disp_histogram:
|
78
|
+
c = HistogramColumn('histogram', type=str, width=self.options.default_width*2)
|
63
79
|
self.addColumn(c)
|
64
80
|
|
81
|
+
# if non-numeric grouping, reverse sort by count at end of load
|
82
|
+
if not any(vd.isNumeric(c) for c in self.groupByCols):
|
83
|
+
self._ordering = [('count', True)]
|
84
|
+
|
85
|
+
def loader(self):
|
86
|
+
'Generate frequency table.'
|
65
87
|
# two more threads
|
66
88
|
vd.sync(self.addAggregateCols(),
|
67
89
|
self.groupRows(self.updateLargest))
|
68
90
|
|
91
|
+
def afterLoad(self):
|
92
|
+
super().afterLoad()
|
69
93
|
if self.nCols > len(self.groupByCols)+3: # hide percent/histogram if aggregations added
|
70
94
|
self.column('percent').hide()
|
71
95
|
self.column('histogram').hide()
|
72
96
|
|
73
|
-
if not [c for c in self.groupByCols if vd.isNumeric(c)]:
|
74
|
-
self.orderBy(self.column('count'), reverse=True)
|
75
|
-
|
76
97
|
def openRow(self, row):
|
77
98
|
'open copy of source sheet with rows that are grouped in current row'
|
78
99
|
if row.sourcerows:
|
79
100
|
vs = copy(self.source)
|
80
|
-
vs.
|
101
|
+
vs.names = vs.names + [vd.valueNames(row.discrete_keys, row.numeric_key)]
|
81
102
|
vs.rows=copy(row.sourcerows)
|
82
|
-
vs.source=self.source
|
83
103
|
return vs
|
84
104
|
vd.warning("no source rows")
|
85
105
|
|
86
106
|
def openRows(self, rows):
|
87
107
|
vs = copy(self.source)
|
88
|
-
vs.
|
108
|
+
vs.names = vs.names + ["several"]
|
109
|
+
vs.source = self
|
89
110
|
vs.rows = list(itertools.chain.from_iterable(row.sourcerows for row in rows))
|
90
111
|
return vs
|
91
112
|
|
@@ -94,23 +115,50 @@ class FreqTableSheet(PivotSheet):
|
|
94
115
|
|
95
116
|
|
96
117
|
class FreqTableSheetSummary(FreqTableSheet):
|
97
|
-
'Append a PivotGroupRow to
|
98
|
-
|
99
|
-
def reload(self):
|
100
|
-
FreqTableSheet.reload.__wrapped__(self)
|
118
|
+
'Append a PivotGroupRow to FreqTableSheet with only selectedRows.'
|
119
|
+
def afterLoad(self):
|
101
120
|
self.addRow(PivotGroupRow(['Selected'], (0,0), self.source.selectedRows, {}))
|
121
|
+
super().afterLoad()
|
102
122
|
|
103
|
-
Sheet.addCommand('F', 'freq-col', 'vd.push(FreqTableSheet(sheet, cursorCol))', 'open Frequency Table grouped on current column, with aggregations of other columns')
|
104
|
-
Sheet.addCommand('gF', 'freq-keys', 'vd.push(FreqTableSheet(sheet, *keyCols))', 'open Frequency Table grouped by all key columns on source sheet, with aggregations of other columns')
|
105
|
-
Sheet.addCommand('zF', 'freq-summary', 'vd.push(FreqTableSheetSummary(sheet, Column("Total", sheet=sheet, getter=lambda col, row: "Total")))', 'open one-line summary for all rows and selected rows')
|
106
123
|
|
107
|
-
|
124
|
+
def makeFreqTableSheetSummary(sheet, *groupByCols):
|
125
|
+
return FreqTableSheetSummary(sheet.name,
|
126
|
+
'%s_freq' % '-'.join(col.name for col in groupByCols),
|
127
|
+
groupByCols=groupByCols,
|
128
|
+
source=sheet)
|
129
|
+
|
130
|
+
|
131
|
+
@VisiData.api
|
132
|
+
class FreqTablePreviewSheet(Sheet):
|
133
|
+
@property
|
134
|
+
def rows(self):
|
135
|
+
return self.source.cursorRow.sourcerows
|
136
|
+
|
137
|
+
|
138
|
+
FreqTableSheet.addCommand('', 'open-preview', 'vd.push(FreqTablePreviewSheet(sheet.name, "preview", source=sheet, columns=source.columns), pane=2); vd.options.disp_splitwin_pct=50', 'open split preview of source rows at cursor')
|
139
|
+
|
140
|
+
Sheet.addCommand('F', 'freq-col', 'vd.push(makeFreqTable(sheet, cursorCol))', 'open Frequency Table grouped on current column, with aggregations of other columns')
|
141
|
+
Sheet.addCommand('gF', 'freq-keys', 'vd.push(makeFreqTable(sheet, *keyCols))', 'open Frequency Table grouped by all key columns on source sheet, with aggregations of other columns')
|
142
|
+
Sheet.addCommand('zF', 'freq-summary', 'vd.push(makeFreqTableSheetSummary(sheet, Column("Total", sheet=sheet, getter=lambda col, row: "Total")))', 'open one-line summary for all rows and selected rows')
|
143
|
+
|
144
|
+
ColumnsSheet.addCommand(ENTER, 'freq-row', 'vd.push(makeFreqTable(source[0], cursorRow))', 'open a Frequency Table sheet grouped on column referenced in current row')
|
108
145
|
vd.addMenuItem('Data', 'Frequency table', 'current row', 'freq-row')
|
109
146
|
|
110
147
|
FreqTableSheet.addCommand('gu', 'unselect-rows', 'unselect(selectedRows)', 'unselect all source rows grouped in current row')
|
111
148
|
FreqTableSheet.addCommand('g'+ENTER, 'dive-selected', 'vd.push(openRows(selectedRows))', 'open copy of source sheet with rows that are grouped in selected rows')
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
149
|
+
FreqTableSheet.addCommand('', 'select-first', 'for r in rows: source.select([r.sourcerows[0]])', 'select first source row in each bin')
|
150
|
+
|
151
|
+
FreqTableSheet.init('largest', lambda: 1)
|
152
|
+
|
153
|
+
vd.addGlobals(
|
154
|
+
makeFreqTable=makeFreqTable,
|
155
|
+
makeFreqTableSheetSummary=makeFreqTableSheetSummary,
|
156
|
+
FreqTableSheet=FreqTableSheet,
|
157
|
+
FreqTableSheetSummary=FreqTableSheetSummary,
|
158
|
+
HistogramColumn=HistogramColumn,
|
159
|
+
)
|
160
|
+
|
161
|
+
vd.addMenuItems('''
|
162
|
+
Data > Frequency table > current column > freq-col
|
163
|
+
Data > Frequency table > key columns > freq-keys
|
164
|
+
''')
|