Matlab: построение частотного распределения с помощью кривой

Мне нужно построить 10 частотных распределений на одном графике. Чтобы все было аккуратно, я хотел бы избежать создания гистограммы с ячейками и предпочел бы иметь линии, которые следуют контуру каждого графика гистограммы.

Я попробовал следующее

[counts, bins] = hist(data);
plot(bins, counts)

Но это дает мне очень неточную и неровную линию.

Я читал о ksdensity, который дает мне хорошую кривую, но изменяет масштаб моей оси Y, и мне нужно иметь возможность считывать частоты по оси Y.

Можете ли вы порекомендовать что-нибудь еще?


person Kaly    schedule 26.05.2014    source источник


Ответы (2)


Вы используете количество ячеек по умолчанию для своей гистограммы и, как я предполагаю, для расчетов оценки плотности ядра.

В зависимости от того, сколько точек данных у вас есть, это определенно не будет оптимальным, как вы обнаружили. Первое, что нужно попробовать, это рассчитать оптимальную ширину бина. чтобы получить самую плавную кривую, одновременно сохраняя базовый PDF как можно лучше. (см. также здесь, здесь и здесь);

Если вам по-прежнему не нравится, насколько гладким получается график, вы можете попробовать использовать выходные данные bins из hist в качестве дополнительных входных данных для ksdensity. Возможно что-то вроде этого:

[kcounts,kbins] = ksdensity(data,bins,'npoints',length(bins));

У меня нет ваших данных, поэтому вам, возможно, придется немного поиграть с параметрами, чтобы получить именно то, что вы хотите.

В качестве альтернативы вы можете попробовать разместить spline по точкам, полученным из hist, и вместо этого построить график.

Некоторый код:

data = randn(1,1e4);

optN = sshist(data);

figure(1)
[N,Center] = hist(data);
[Nopt,CenterOpt] = hist(data,optN);
[f,xi] = ksdensity(data,CenterOpt);

dN = mode(diff(Center));
dNopt = mode(diff(CenterOpt));

plot(Center,N/dN,'.-',CenterOpt,Nopt/dNopt,'.-',xi,f*length(data),'.-')
legend('Default','Optimum','ksdensity')

Результат:

Различные стили гистограммы

Обратите внимание, что «оптимальная» ширина бина сохраняет некоторую тонкую структуру распределения (мне пришлось запустить это пару раз, чтобы получить пики), в то время как ksdensity дает гладкую кривую. В зависимости от того, что вы ищете в своих данных, это может быть как хорошо, так и плохо.

person craigim    schedule 26.05.2014
comment
Обратите внимание, что масштабирование по оси Y всегда будет зависеть от ширины ячейки. ksdensity вернет кривую, нормализованную до площади 1, поэтому вы можете масштабировать ее, умножив на length(data), чтобы вместо этого ось Y была пропорциональна количеству точек. - person craigim; 27.05.2014
comment
как именно вы масштабируете, умножая на length(data)? - person cosmictypist; 12.08.2015
comment
Я не уверен, что понимаю ваш вопрос. В приведенном выше примере кода я выполнил умножение в предпоследней строке: f*length(data) - person craigim; 12.08.2015
comment
Также обратите внимание, что обе гистограммы нормализованы по ширине бина, чтобы превратить их в число на частоту ширины бина, так что интеграл каждой кривой гистограммы равен общему количеству объектов. Умножение kdensity на общее количество объектов делает его интегральное соответствие с другими. - person craigim; 12.08.2015

Как насчет интерполяции с помощью сплайнов?

nbins = 10; %// number of bins for original histogram
n_interp = 500; %// number of values for interpolation
[counts, bins] = hist(data, nbins);
bins_interp = linspace(bins(1), bins(end), n_interp);
counts_interp = interp1(bins, counts, bins_interp, 'spline');
plot(bins, counts) %// original histogram
figure
plot(bins_interp, counts_interp) %// interpolated histogram

Пример: пусть

data = randn(1,1e4);

Исходная гистограмма:

введите здесь описание изображения

Интерполировано:

введите здесь описание изображения

Следуя вашему коду, ось Y на приведенных выше рисунках дает количество, а не плотность вероятности. Чтобы получить плотность вероятности, вам нужно нормализовать:

normalization = 1/(bins(2)-bins(1))/sum(counts);
plot(bins, counts*normalization) %// original histogram
plot(bins_interp, counts_interp*normalization) %// interpolated histogram

Проверить: общая площадь должна быть примерно 1:

>> trapz(bins_interp, counts_interp*normalization)
ans =
    1.0009
person Luis Mendo    schedule 26.05.2014