I’d love a Block that generates a word cloud based on the data in both specific and multiple fields at a time. In a perfect world, you’d have the ability to exclude articles 🙃
@Shannon_Ratliff Wondering if you found any workaround to this?
I want to sort across review tags based on frequency and density, and need a word-cloud functionality to visualise it easily
A word cloud starts with a tag array. The tag array must be extracted programmatically (of course) and from that array, you can derive analytics. This would be difficult to do in Zapier (I’m guessing) and so, I do it with script plus the Airtable API like this.
I have a super simple “Links” table for interesting things I find around the web.
On the right hand side I have a Tags column with Multi-Select values corresponding to tags that I given each link. Having a WordCloud Block would be awesome if it could ingest that column of tags and enable me to click on a specific word in the Word Cloud and have it automatically filter results shown to just that tag or combination of tags.
Yeah, that would be nice. We do a lot with tags and analytics based on text. This is a utility one of our devs created for us internally - nothing fancy but provides a frequency distribution and some basics for filtering and links to specific records.
Code is free to use and there are likely a bazillion ways to make it better.
/*
***********************************************************
Airdrop - Word Cloud Example
Copyright (c) 2020 by Global Technologies Corporation
ALL RIGHTS RESERVED
***********************************************************
*/
output.markdown('# WordCloud');
// select the table
var srcTable = await input.tableAsync('Enter the table name:');
// select the key field
let keyFieldName = await input.fieldAsync("Select the key field", srcTable);
// select the source field
let srcField = await input.fieldAsync("Pick a tags field", srcTable);
// open the table
let table = base.getTable(srcTable.name);
let field = table.getField(srcField.name);
let keyName = table.getField(keyFieldName.name);
// Load all of the records in the table
let result = await table.selectRecordsAsync();
// Find every record we need to update
let oTags = {};
let aTags = [];
let aUniqueTags = [];
for (let record of result.records)
{
// get the value of the tag source
let thisKey = record.getCellValue(keyName);
let thisValue = record.getCellValue(field);
// Skip records which don't have the value set, so the value is null
if (!thisValue) {
continue;
}
// iterate across the tag items
for (let i in thisValue)
{
// output.markdown(thisValue[i].name);
try {
oTags[thisValue[i].name] = {
"Count" : oTags[thisValue[i].name].Count += 1,
"Frequency" : "█".repeat(oTags[thisValue[i].name].Count + 1)
}
} catch (e) {
oTags[thisValue[i].name] = {
"Count" : 1,
"Frequency" : "█".repeat(1)
}
aUniqueTags.push(thisValue[i].name);
}
aTags.push([thisKey, thisValue[i].name, "https://airtable.com/tblurHro7b5UQBtl3/viwTO76HyzTGexvS5/" + record.id]);
}
}
// sort the link list
aTags.sort();
// menu
while (true)
{
output.clear();
output.markdown('# WordCloud');
// output.inspect(oTags)
output.markdown('## Frequency Distribution');
output.table(oTags)
// display the tag buttons
let thisTag = await input.buttonsAsync('Select:', aUniqueTags);
// filter the array
let aFilteredTags = filterByTagName(aTags, thisTag, 1);
// create markdown table
m = "";
m += "| " + keyFieldName.name + " | " + srcField.name + " |\n";
m += "| ----------------------------- | ----------- |\n";
for (var i in aFilteredTags)
{
m += "| [" + aFilteredTags[i][0] + "](" + aFilteredTags[i][2] + ")|" + aFilteredTags[i][1] + "|\n";
}
// render the filtered table
output.markdown(m)
// display the tag buttons
let shouldContinue = await input.buttonsAsync(
'Filter Again?',
[
{label: 'Yes', value: 'yes'},
{label: 'No', value: 'no'},
],
);
if (shouldContinue === 'no') {
output.clear();
break;
}
}
function filterByTagName(array, thisTag, position) {
return array.filter(innerArray => innerArray[position] == thisTag);
}