序列周期性检测

基于FFT

信号的连续/离散性 v.s. 周期性/非周期性,在时域与频域中是相互决定的。即:时域连续,频域非周期;时域离散,频域周期;时域周期,频域离散;时域非周期,频域连续。

因此,将序列做FFT后,如果是准离散信号(体现为大毛刺),则可认为该序列为近似周期性。

基于FFT的周期性检测方法,具体流程为:(1)对输入信号做FFT;(2)检测FFT结果离散性(是否存在大毛刺);(3)根据FFT结果是否为离散,给出周期性判断结果。

代码示例

基于自相关函数

周期函数的自相关函数是具有与原函数相同周期的函数。

代码示例

Python - 基于自相关函数的周期性检测方法

核心思想

求自相关函数,比较第0个值(无延迟)与可能周期位置(或第一个峰值)的值是否相近

1
2
3
4
5
6
7
8
9
10
11
12
13
from statsmodels.tsa.stattools import acf

rx = acf(x,fft=True, unbiased=True, nlags=np.size(x)-1)

if param['if_judge_periodicity_for_known_period'] == True:
peak_value = rx[param['period_size']]
else:
peaks_detected = peakdetect(rx)[0] # 预估周期大概有多
peak_value = peaks_detected[0][1] # 第1个最大峰值的实际值

periodicity_ratio = peak_value/rx[0]

# 后续比较periodicity_ratio与预定义阈值

Java - 正则表达式示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegExDemo
{
public static void main(String[] args)
{
String content = "this is a test";

// 整句:.*is\s+.*
String pattern1 = ".*is\\s+.*";
// 空白符:\s
String pattern2 = "\\s";
// 部分:is
String pattern3 = "is";


// --------------- Pattern ---------------
// 快速是否匹配
boolean isMatch = Pattern.matches(pattern1, content);
System.out.println(isMatch);

Pattern p1 = Pattern.compile(pattern1);
Pattern p2 = Pattern.compile(pattern2);
Pattern p3 = Pattern.compile(pattern3);

// 分割字符串
String[] fields = p2.split(content);
for(String s : fields)
{
System.out.println(s);
}

// 获取Matcher
Matcher m1 = p1.matcher(content);
Matcher m2 = p2.matcher(content);
Matcher m3 = p3.matcher(content);


// --------------- Matcher ---------------
// 匹配整句 matches
isMatch = m1.matches();
System.out.println(isMatch);
isMatch = m2.matches();
System.out.println(isMatch);

// 匹配任意部分 find。如想匹配多次,则反复调用
isMatch = m3.find();
System.out.println(isMatch);
// 匹配到的子串,在整句的[)idx及内容
System.out.println(m3.start() + ", " + m3.end() + ", " + m3.group());

/* 分组操作,捕获组是通过从左至右数括号的方式来编号。例如,表达式((A)(B(C)))有四个组:
* ((A)(B(C))), (A), (B(C)), (C)*/
Pattern pg = Pattern.compile("([a-z]+)(\\s+)");
Matcher mg = pg.matcher(content);
mg.find();
// group(0)总是代表整个表达式。该组不包括在 groupCount的返回值中。
for(int i = 1; i <= mg.groupCount(); ++i)
{
System.out.println(mg.start(i) + ", " + mg.end(i) + ", " + mg.group(i));
}
}
}

/*
* \ 转义
* ^ 字符串开始
* $ 字符串结尾
* . 除换行符外所有字符
*
* * 0次以上,{0,}
* + 1次以上,{1,}
* ? 0次或1次,{0,1}
* {n} n次
* {n,} n次以上
* {n,m} 至少n次,至多m次
* ? 当此字符紧随任何其他限定符(*、+、?、{n}、{n,}、{n,m})之后时,匹配模式是“非贪心的”最小匹配。
* 例如,在字符串“oooo”中,o+匹配所有“o”,而o+?只匹配单个“o”。
*
* x|y 匹配x或y
* [xyz] 字符集合。匹配所包含的任意一个字符。[a-z]任意字符。[0-9]任意数字。
* [^xyz] 负值字符集合。匹配未包含的任意一个字符。[^a-z]任意非字符。[^0-9]任意非数字。
* (p) 匹配pattern并获取这一匹配。
* (?:p) 匹配pattern但不获取匹配结果。
*
* \b 匹配一个单词边界,也就是指单词和空格间的位置。
* 例如,er\b可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。
* \B 匹配非单词边界。
* \w 任意英文字符。等价于[a-zA-Z_0-9]。
* \W 任意非英文字符。等价于[^a-zA-Z_0-9]。
* \d 匹配一个数字。[0-9]
* \D 匹配一个非数字。[^0-9]
* \s 匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
* \S 匹配任何可见字符。等价于[^ \f\n\r\t\v]。
*/

Java - XML解析示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import java.io.ByteArrayInputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class XmlParserDemo
{
/*
<?xml version="1.0" encoding="UTF-8"?>
<routetable>
<route>
<da>138517</da>
<ne>SMSC1</ne>
</route>
<route>
<da>139139</da>
<ne> SMSC2</ne>
</route>
</routetable>
*/
private static final String xmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<routetable>"
+ "<route><da>138517</da>"
+ "<ne>SMSC1</ne></route>"
+ "<route><da>139139</da>"
+ "<ne>SMSC2</ne></route>"
+ "</routetable>";

public static void main(String[] args)
{
try
{
// 生成一个Dom解析器
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();

// 解析XML
//Document document = db.parse(new File("test.xml"));
Document document = db.parse(new ByteArrayInputStream(xmlString.getBytes()));
document.getDocumentElement().normalize();

NodeList table = document.getElementsByTagName("routetable");
System.out.println("routetable list len = " + table.getLength());
for(int i = 0; i < table.getLength(); ++i)
{
System.out.println("routetable " + i + " name = " + table.item(i).getNodeName());
NodeList list = table.item(i).getChildNodes();
System.out.println("route list len = " + list.getLength());
}

System.out.println();

NodeList routeList = document.getElementsByTagName("route");
for(int i = 0; i < routeList.getLength(); ++i)
{
Node route = routeList.item(i);
if(route.getNodeType() == Node.ELEMENT_NODE)
{
Element element = (Element) route;
System.out.println("id = " + (element.getAttribute("id").isEmpty() ? "no ID" : element.getAttribute("id")));
System.out.println("da -> " + element.getElementsByTagName("da").item(0).getTextContent());
System.out.println("ne -> " + element.getElementsByTagName("ne").item(0).getTextContent());
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}

Java - Collections示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

public class CollectionsDemo
{

public static void main(String[] args)
{
ArrayList<Integer> myList = new ArrayList<Integer>();
HashSet<String> mySet = new HashSet<String>();
HashMap<String, Integer> myMap = new HashMap<String, Integer>();

// ---------- adding ----------
myList.add(2);
myList.add(1);
myList.add(3);
mySet.add("item2");
mySet.add("item1");
mySet.add("item3");
myMap.put("key1", 999);
myMap.put("key2", 888);
myMap.put("key3", 777);
myMap.put("key4", 777);
myMap.put("key5", 666);

// ---------- searching ----------
System.out.println(myList.contains(1));
System.out.println(myList.indexOf(1));
System.out.println(mySet.contains("item1"));
System.out.println(myMap.containsKey("key1"));

System.out.println();

// ---------- removing & iterating ----------
// arg is idx
myList.remove(2);
for(int i = 0; i < myList.size(); ++i)
{
System.out.println(myList.get(i));
}
myList.add(3);
for(int i : myList)
{
System.out.println(i);
}

// for iteration delete: record first, delete after iterating
mySet.remove("item2");
Iterator<String> it = mySet.iterator();// <---------- iterator
while(it.hasNext())
{
String cur = it.next();
System.out.println(cur);
}
mySet.add("item2");
for(String s : mySet)// <---------- for each
{
System.out.println(s);
}

myMap.remove("key1");
Iterator<Entry<String, Integer>> it2 = myMap.entrySet().iterator();// <---------- iterator
while(it2.hasNext())
{
Entry<String, Integer> entry = it2.next();
System.out.println("key: " + entry.getKey() + ", value: " + entry.getValue());
}
myMap.put("key1", 999);
for(Entry<String, Integer> entry : myMap.entrySet())// <---------- for each
{
System.out.println("key: " + entry.getKey() + ", value: " + entry.getValue());
}

System.out.println();

// ---------- sorting ----------
Collections.sort(myList);
for(int i : myList)
{
System.out.println(i);
}

ArrayList<String> mySetList = new ArrayList<String>(mySet);
Collections.sort(mySetList, (s1, s2) -> s1.compareTo(s2) * -1);// <---------- sort reverse
for(String s : mySetList)
{
System.out.println(s);
}

List<Entry<String, Integer>> entryList = new ArrayList<Entry<String, Integer>>(myMap.entrySet());
Collections.sort(entryList, (en1, en2) -> en1.getKey().compareTo(en2.getKey()) * -1);// <---------- by key
for(Entry<String, Integer> en : entryList)
{
System.out.println("key: " + en.getKey() + ", value: " + en.getValue());
}
Collections.sort(entryList, (en1, en2) -> {
if(!en1.getValue().equals(en2.getValue()))
{
return en1.getValue().compareTo(en2.getValue()) * -1;
}
else
{
return en1.getKey().compareTo(en2.getKey());
}
});// <---------- by value
for(Entry<String, Integer> en : entryList)
{
System.out.println("key: " + en.getKey() + ", value: " + en.getValue());
}
}
}