Способ 1:
{k:np.sum(a==k) for k in set(a.ravel().tolist())}
или немного более читаемо
count = lambda A, key : np.sum(A==key)
unique_keys = set(A.ravel().tolist())
return {key : count(A,key) for key in unique_keys}
Прогулка по нему:
{...}
set(a.ravel().tolist())
a.ravel
выравнивает изображение ; в списке, он может быть передан в набор , который является контейнером для уникальных элементов.
np.sum(a==k)
Подсчитайте, сколько раз элемент находится на изображении. Этот не самый эффективный способ сделать это , но помещает гистограмму в запрошенный вами формат
Взятые вместе, если ваше изображение 3x3
a = np.array([[1,2,3],[1,3,3],[3,3,3]])
, затем
set(a.ravel().tolist()) # yields set([1, 2, 3])
, и все выражение дает
{1: 2, 2: 1, 3: 6}
Способ 2
from PIL.Image import fromarray
b = fromarray(a.astype(np.uint8)) # convert to a PIL image
hist = {idx:count for idx, count in enumerate(b.histogram()) if count}
Это работает очень аналогично (используя понимание словаря), но использует функциональность гистограммы PIL , а перечисляет для извлечения индексов.
«Binning»
Если вы хотите иметь «бункеры» цветов, как вы указали, то оставшаяся работа просто определяет структуру вашего бина, что будет сделано многими способами. Например, в предыдущем примере мы можем создавать фиксированные ячейки с фиксированным размером
num_bins = 2
b = fromarray(a.astype(np.uint8)//num_bins) # convert to a PIL image, binned
hist = {idx*num_bins:count for idx, count in enumerate(b.histogram()) if count}
range_input
в существующем скрипте жестко запрограммирован. Это неудовлетворительно, потому что не позволяет проводить анализ для каждого учащегося. Чтобы это исправить, вам нужно просмотреть данные для каждого учащегося и выполнить «countbold» для каждого учащегося.
Предположим, что «C3: S3» - это диапазон для одного ученика. Давайте также предположим, что данные для других учащихся содержатся в каждой последующей строке, и что есть две строки заголовка.
Для этого нужно:
ALast
. range_input
, рассмотренный ниже. Примечание:
Целевой диапазон (range_output
) рассчитывается для каждой строки с использованием getRange
(строка, столбец). Это можно было бы сделать, сохранив значения в массиве и обновив все значения в одном процессе, но я подумал, что было бы лучше сохранить подход, уже использованный OP, и не усложнять ситуацию. Если есть много студентов, и выполнение кода занимает слишком много времени, то обновление счетчиков по массиву будет более эффективным.
Диапазон ввода (range_input
) определяется с помощью getRange
(строка, столбец, numRows, numColumns).
function so54260768() {
// Setup spreadsheet and target sheet
var book = SpreadsheetApp.getActiveSpreadsheet();
var sheet = book.getActiveSheet();
// get the number of students in Column A
var Avals = book.getRange("A1:A").getValues(); // assuming rows one and two are headers
var Alast = Avals.filter(String).length;
//Logger.log("DEBUG: The last row on A = " + Alast);// DEBUG
// number of columns in the data range
var NumberofColumns = 17;
// get the data for all students
var range_input = sheet.getRange(3, 3, Alast - 2, NumberofColumns); // the first two rows are headers
var cell_styles = range_input.getFontWeights();
// start loop though each row - one row per student
for (z = 0; z < Alast - 2; z++) {
// set the bold counter to zero
var count = 0;
//loop through the cells in this row; count the cells that are bold
for (var i = 0; i < NumberofColumns; i++) {
if (cell_styles[z][i] === "bold") {
count = count + 1;
}
}
//Logger.log("DEBUG: row="+(z+3)+", count="+count);//DEBUG
var range_output = sheet.getRange(z + 3, 14).setValue(count); //. row, column
}
}