Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中的滚动中值算法_C_Algorithm_R_Statistics_Median - Fatal编程技术网

C语言中的滚动中值算法

C语言中的滚动中值算法,c,algorithm,r,statistics,median,C,Algorithm,R,Statistics,Median,我目前正在研究一种用C实现滚动中值滤波器(类似于滚动均值滤波器)的算法。从我对文献的搜索来看,似乎有两种相当有效的方法。第一种方法是对初始值窗口进行排序,然后执行二进制搜索以插入新值,并在每次迭代中删除现有值 第二(来自Hardle和SigigER,1995,JRSS-C,算法296)建立了一个双端堆结构,一端有一个最大堆,另一个在一个堆上,中间在中间。这将产生一个线性时间算法,而不是O(n logn) 我的问题是:实现前者是可行的,但我需要在数百万个时间序列上运行它,因此效率非常重要。后者很难

我目前正在研究一种用C实现滚动中值滤波器(类似于滚动均值滤波器)的算法。从我对文献的搜索来看,似乎有两种相当有效的方法。第一种方法是对初始值窗口进行排序,然后执行二进制搜索以插入新值,并在每次迭代中删除现有值

第二(来自Hardle和SigigER,1995,JRSS-C,算法296)建立了一个双端堆结构,一端有一个最大堆,另一个在一个堆上,中间在中间。这将产生一个线性时间算法,而不是O(n logn)

我的问题是:实现前者是可行的,但我需要在数百万个时间序列上运行它,因此效率非常重要。后者很难实施。我在R的stats包的Trunmed.c文件中找到了代码,但它相当难以识别

有人知道线性时间滚动中值算法的C语言实现吗


<>编辑:链接到TunMun.C代码

< P>我已经看过R的代码> SRC/Labe/Stcs/Src/Tunun.C./Cuth>几次,因为我也希望在一个独立的C++类/C子程序中也有类似的东西。请注意,这实际上是一个两个实现,请参见
src/library/stats/man/runmed.Rd
(帮助文件的源代码),其中

\details{
  Apart from the end values, the result \code{y = runmed(x, k)} simply has
  \code{y[j] = median(x[(j-k2):(j+k2)])} (k = 2*k2+1), computed very
  efficiently.

  The two algorithms are internally entirely different:
  \describe{
    \item{"Turlach"}{is the Härdle-Steiger
      algorithm (see Ref.) as implemented by Berwin Turlach.
      A tree algorithm is used, ensuring performance \eqn{O(n \log
        k)}{O(n * log(k))} where \code{n <- length(x)} which is
      asymptotically optimal.}
    \item{"Stuetzle"}{is the (older) Stuetzle-Friedman implementation
      which makes use of median \emph{updating} when one observation
      enters and one leaves the smoothing window.  While this performs as
      \eqn{O(n \times k)}{O(n * k)} which is slower asymptotically, it is
      considerably faster for small \eqn{k} or \eqn{n}.}
  }
}
\n详细信息{
除了结束值之外,result\code{y=runmed(x,k)}只是
\代码{y[j]=中位数(x[(j-k2):(j+k2)]}(k=2*k2+1),计算非常精确
效率高。
这两种算法在内部完全不同:
\描述{
\项目{“Turlach”}{是Härdle Steiger
由Berwin Turlach实现的算法(见参考文献)。
使用树算法,确保性能\eqn{O(n\log

k) }{O(n*log(k))}其中\code{n如果您只需要平滑的平均值,一个快速/简单的方法是将最新值乘以x,将平均值乘以(1-x),然后将它们相加。这将成为新的平均值

编辑:不是用户要求的,也不是统计上有效的,但足以用于许多用途。

我将把它留在这里(尽管有反对票)对于搜索!

如果您能够参考值作为时间点的函数,您可以通过替换对值进行采样,以在置信区间内生成引导中值。这可能使您计算近似中值的效率高于将传入值不断排序到数据结构中的效率ure.

以下是量化数据的简单算法(几个月后):

“”“median1.py:移动量化中值1d,例如8位数据
方法:缓存中间值,以便更宽的窗口更快。
代码很简单——没有堆,没有树。
关键词:中值滤波、移动中值、运行中值、numpy、scipy
见Perreault+Hebert,《恒定时间中值滤波》,2007年,
http://nomis80.org/ctmf.html: 漂亮的6页纸和C代码,
主要用于二维图像
例子:
y=中间带(x,窗=窗,nlevel=nlevel)
使用:
med=Median1(nlevel,window,counts=np.bincount(x[0:window]))
med.addsub(+,-)--请参见Perreault中的图片
m=med.median()--使用缓存的m,求和
工作原理:
图片nlevel=8,window=3--3 1s,在一个由8个计数器组成的数组中:
计数:.1..1.1。
总数:011223
^和[3]<2一个较短的列表,len(y)=len(x)-窗口+1
"""
断言len(x)>=window(len(x),window)
#np.clip(x,0,nlevel-1,out=x)
#碳纤维http://scipy.org/Cookbook/Rebinning
cnt=np.bincount(x[0:window])
med=Median1(nlevel=nlevel,window=window,counts=cnt)
y=(透镜(x)-窗口+1)*[0]
y[0]=中间值()
对于x范围内的j(透镜(x)-窗口):
med.addsub(x[j+窗口],x[j])
y[j+1]=中间值()
返回y#列表
#返回np.数组(y)
def pad0_uuuux(托伦):
“”“用0 s、numpy数组或列表填充x”“”
n=托伦-伦(x)
如果n>0:
尝试:
x=np.r_ux,np.zero(n,dtype=x[0].dtype)]
除名称错误外:
x+=n*[0]
返回x
#...............................................................................
如果名称=“\uuuuu main\uuuuuuuu”:
Len=10000
窗口=3
nlevel=256
周期=100
np.设置打印选项(2,阈值=100,边缘项=10)
#打印介质(np.arange(3),3)
正弦波=(np.sin(2*np.pi*np.arange(Len)/周期)
+1)*(NLL-1级)/2
x=np.asarray(正弦波,整数)
打印“x:”,x
对于窗口输入(3、31、63、127、255):
如果窗口>镜头:继续
打印“medianfilter:Len=%d window=%d nlevel=%d:”%(Len,window,nlevel)
y=中间过滤器(x,窗口=窗口,nlevel=nlevel)
打印np.数组(y)
#中端1.py
我已经做了一个测试。更多细节在这个问题中:

示例用法:

int main(int argc, char* argv[])
{
   int i, v;
   Mediator* m = MediatorNew(15);
 
   for (i=0; i<30; i++) {
      v = rand() & 127;
      printf("Inserting %3d \n", v);
      MediatorInsert(m, v);
      v = MediatorMedian(m);
      printf("Median = %3d.\n\n", v);
      ShowTree(m);
   }
}
intmain(intargc,char*argv[])
{
int i,v;
调解员*m=调解员新(15);

对于(i=0;i我使用此增量中值估值器:

median += eta * sgn(sample - median)
mean += eta * (sample - mean)
其形式与更常见的均值估值器相同:

median += eta * sgn(sample - median)
mean += eta * (sample - mean)
这里eta是一个小的学习率参数(例如
0.001
),而
sgn()
是返回
{-1,0,1}
中一个的signum函数。(如果数据是非平稳的,并且希望跟踪随时间的变化,则使用如下常量
eta
;否则,对于平稳源,使用类似
eta=1/n
的方法进行收敛,其中
n
是迄今为止看到的样本数。)

此外,我还修改了中值估计器,使其适用于任意分位数。通常,a告诉您将数据分成两部分的值:
p
1-p
。下面以增量方式估计该值:

quantile += eta * (sgn(sample - quantile) + 2.0 * p - 1.0)
p
应在
[0,1]
范围内。这实质上改变了
sgn()
iter = tree.find_by_order(value)
order = tree.order_of_key(value)
#if !defined(GNU_ORDER_STATISTIC_SET_H)
#define GNU_ORDER_STATISTIC_SET_H
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

// A red-black tree table storing ints and their order
// statistics. Note that since the tree uses
// tree_order_statistics_node_update as its update policy, then it
// includes its methods by_order and order_of_key.
template <typename T>
using t_order_statistic_set = __gnu_pbds::tree<
                                  T,
                                  __gnu_pbds::null_type,
                                  std::less<T>,
                                  __gnu_pbds::rb_tree_tag,
                                  // This policy updates nodes'  metadata for order statistics.
                                  __gnu_pbds::tree_order_statistics_node_update>;

#endif //GNU_ORDER_STATISTIC_SET_H
{
totalcount++;
newmedian=lastmedian+(newvalue>lastmedian?1:-1)*(lastmedian==0?newvalue: lastmedian/totalcount*2);
}
package MedianOfIntegerStream;

import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;


public class MedianOfIntegerStream {

    public Set<Integer> rightMinSet;
    public Set<Integer> leftMaxSet;
    public int numOfElements;

    public MedianOfIntegerStream() {
        rightMinSet = new TreeSet<Integer>();
        leftMaxSet = new TreeSet<Integer>(new DescendingComparator());
        numOfElements = 0;
    }

    public void addNumberToStream(Integer num) {
        leftMaxSet.add(num);

        Iterator<Integer> iterMax = leftMaxSet.iterator();
        Iterator<Integer> iterMin = rightMinSet.iterator();
        int maxEl = iterMax.next();
        int minEl = 0;
        if (iterMin.hasNext()) {
            minEl = iterMin.next();
        }

        if (numOfElements % 2 == 0) {
            if (numOfElements == 0) {
                numOfElements++;
                return;
            } else if (maxEl > minEl) {
                iterMax.remove();

                if (minEl != 0) {
                    iterMin.remove();
                }
                leftMaxSet.add(minEl);
                rightMinSet.add(maxEl);
            }
        } else {

            if (maxEl != 0) {
                iterMax.remove();
            }

            rightMinSet.add(maxEl);
        }
        numOfElements++;
    }

    public Double getMedian() {
        if (numOfElements % 2 != 0)
            return new Double(leftMaxSet.iterator().next());
        else
            return (leftMaxSet.iterator().next() + rightMinSet.iterator().next()) / 2.0;
    }

    private class DescendingComparator implements Comparator<Integer> {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o2 - o1;
        }
    }

    public static void main(String[] args) {
        MedianOfIntegerStream streamMedian = new MedianOfIntegerStream();

        streamMedian.addNumberToStream(1);
        System.out.println(streamMedian.getMedian()); // should be 1

        streamMedian.addNumberToStream(5);
        streamMedian.addNumberToStream(10);
        streamMedian.addNumberToStream(12);
        streamMedian.addNumberToStream(2);
        System.out.println(streamMedian.getMedian()); // should be 5

        streamMedian.addNumberToStream(3);
        streamMedian.addNumberToStream(8);
        streamMedian.addNumberToStream(9);
        System.out.println(streamMedian.getMedian()); // should be 6.5
    }
}
Algorithm- 1- Take two Heap(1 Min Heap and 1 Max Heap) Max Heap will contain first half number of elements Min Heap will contain second half number of elements 2- Compare new number from stream with top of Max Heap, if it is smaller or equal add that number in max heap. Otherwise add number in Min Heap. 3- if min Heap has more elements than Max Heap then remove top element of Min Heap and add in Max Heap. if max Heap has more than one element than in Min Heap then remove top element of Max Heap and add in Min Heap. 4- If Both heaps has equal number of elements then median will be half of sum of max element from Max Heap and min element from Min Heap. Otherwise median will be max element from the first partition.
public class Solution {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        RunningMedianHeaps s = new RunningMedianHeaps();
        int n = in.nextInt();
        for(int a_i=0; a_i < n; a_i++){
            printMedian(s,in.nextInt());
        }
        in.close();       
    }

    public static void printMedian(RunningMedianHeaps s, int nextNum){
            s.addNumberInHeap(nextNum);
            System.out.printf("%.1f\n",s.getMedian());
    }
}

class RunningMedianHeaps{
    PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
    PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(Comparator.reverseOrder());

    public double getMedian() {

        int size = minHeap.size() + maxHeap.size();     
        if(size % 2 == 0)
            return (maxHeap.peek()+minHeap.peek())/2.0;
        return maxHeap.peek()*1.0;
    }

    private void balanceHeaps() {
        if(maxHeap.size() < minHeap.size())
        {
            maxHeap.add(minHeap.poll());
        }   
        else if(maxHeap.size() > 1+minHeap.size())
        {
            minHeap.add(maxHeap.poll());
        }
    }

    public void addNumberInHeap(int num) {
        if(maxHeap.size()==0 || num <= maxHeap.peek())
        {
            maxHeap.add(num);
        }
        else
        {
            minHeap.add(num);
        }
        balanceHeaps();
    }
}
  /// <summary>
  /// Median estimation by histogram, avoids multiple sorting operations for a running median
  /// </summary>
  public class MedianEstimator
  {
    private readonly int m_size2;
    private readonly byte[] m_counts;

    /// <summary>
    /// Estimated median, available right after calling <see cref="Init"/> or <see cref="Update"/>.
    /// </summary>
    public byte Median { get; private set; }

    /// <summary>
    /// Ctor
    /// </summary>
    /// <param name="size">Median size in samples</param>
    /// <param name="maxValue">Maximum expected value in input data</param>
    public MedianEstimator(
      int size,
      byte maxValue)
    {
      m_size2 = size / 2;
      m_counts = new byte[maxValue + 1];
    }

    /// <summary>
    /// Initializes the internal histogram with the passed sample values
    /// </summary>
    /// <param name="values">Array of values, usually the start of the array for a running median</param>
    public void Init(byte[] values)
    {
      for (var i = 0; i < values.Length; i++)
        m_counts[values[i]]++;

      UpdateMedian();
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private void UpdateMedian()
    {
      // The median is the first value up to which counts add to size / 2
      var sum = 0;
      Median = 0;
      for (var i = 0; i < m_counts.Length; i++)
      {
        sum += m_counts[i];
        Median = (byte) i;
        if (sum > m_size2) break;
      }
    }

    /// <summary>
    /// Updates the median estimation by removing <paramref name="last"/> and adding <paramref name="next"/>. These
    /// values must be updated as the running median is applied. If the median length is <i>N</i>, at the sample
    /// <i>i</i>, <paramref name="last"/> is sample at index <i>i</i>-<i>N</i>/2 and <paramref name="next"/> is sample
    /// at index <i>i</i>+<i>N</i>/2+1.
    /// </summary>
    /// <param name="last">Sample at the start of the moving window that is to be removed</param>
    /// <param name="next">Sample at the end of the moving window + 1 that is to be added</param>
    public void Update(byte last, byte next)
    {
      m_counts[last]--;
      m_counts[next]++;

      // The conditions below do not change median value so there is no need to update it
      if (last == next ||
          last < Median && next < Median || // both below median
          last > Median && next > Median) // both above median
        return;

      UpdateMedian();
    }
private void TestMedianEstimator()
{
  var r = new Random();
  const int SIZE = 15;
  const byte MAX_VAL = 80;
  var values = new byte[100000];
  for (var i = 0; i < values.Length; i++)
    values[i] = (byte) (MAX_VAL * r.NextDouble());

  var timer = Stopwatch.StartNew();
  // Running median
  var window = new byte[2 * SIZE + 1];
  var medians = new byte[values.Length];
  for (var i = SIZE; i < values.Length - SIZE - 1; i++)
  {
    for (int j = i - SIZE, k = 0; j <= i + SIZE; j++, k++)
      window[k] = values[j];
    Array.Sort(window);
    medians[i] = window[SIZE];
  }
  timer.Stop();
  var elapsed1 = timer.Elapsed;

  timer.Restart();
  var me = new MedianEstimator(2 * SIZE + 1, MAX_VAL);
  me.Init(values.Slice(0, 2 * SIZE + 1));
  var meMedians = new byte[values.Length];
  for (var i = SIZE; i < values.Length - SIZE - 1; i++)
  {
    meMedians[i] = me.Median;
    me.Update(values[i - SIZE], values[i + SIZE + 1]);
  }
  timer.Stop();
  var elapsed2 = timer.Elapsed;

  WriteLineToLog($"{elapsed1.TotalMilliseconds / elapsed2.TotalMilliseconds:0.00}");

  var diff = 0;
  for (var i = 0; i < meMedians.Length; i++)
    diff += Math.Abs(meMedians[i] - medians[i]);
  WriteLineToLog($"Diff: {diff}");
}