tonglin0325的个人主页

特征预处理——异常值处理

pandas是python特征预处理常用的框架

1.查看数据

加载数据

1
2
3
4
5
6
#-*- coding: utf-8 -*-
import pandas as pd

train_data = pd.read_csv("./data/train.csv")
print(train_data)

pandas显示DataFrame数据的所有列,set_option其他参数参考:Pandas函数set_option()学习笔记

1
2
3
4
5
6
7
8
pd.set_option('expand_frame_repr', False) # 不换行
#pd.set_option('display.width', 200) # 列最多显示多少字符后换行

pd.set_option('display.min_rows', 20) # 至少显示20行数据
pd.set_option('display.max_columns', None) # 显示所有列

print(train_data)

2.查看空值

在pandas中的空值为NaN,isna()等同于isnull()

1
2
print(train_data.isna()) # 判断所有值是否是na,转换成boolean值

对于csv字符串NA,用pandas读取的时候,会转换成NaN,对于字符串None,则不是NaN

统计字段中Nan空值的总数

1
2
print(train_data.isna().sum())

查看某列是NaN的行

1
2
print(train_data[train_data.MiscFeature.isnull()])

查看有NaN值的列名

1
2
3
4
print(train_data.columns[train_data.isnull().any()].tolist())

['LotFrontage', 'Alley', 'MasVnrType', 'MasVnrArea', 'BsmtQual', 'BsmtCond', 'BsmtExposure', 'BsmtFinType1', 'BsmtFinType2', 'Electrical', 'FireplaceQu', 'GarageType', 'GarageYrBlt', 'GarageFinish', 'GarageQual', 'GarageCond', 'PoolQC', 'Fence', 'MiscFeature']

对有Nan值的列的空值比例进行排序

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
total = train_data.isna().sum().sort_values(ascending=False)
percent = (train_data.isna().sum() / train_data.isnull().count()).sort_values(ascending=False)
missing_data = pd.concat([total, percent], axis=1, keys=['Total', 'Percent'])
print(missing_data.head(20))

Total Percent
PoolQC 1453 0.995205
MiscFeature 1406 0.963014
Alley 1369 0.937671
Fence 1179 0.807534
FireplaceQu 690 0.472603
LotFrontage 259 0.177397
GarageYrBlt 81 0.055479
GarageCond 81 0.055479
GarageType 81 0.055479
GarageFinish 81 0.055479
GarageQual 81 0.055479
BsmtFinType2 38 0.026027
BsmtExposure 38 0.026027
BsmtQual 37 0.025342
BsmtCond 37 0.025342
BsmtFinType1 37 0.025342
MasVnrArea 8 0.005479
MasVnrType 8 0.005479
Electrical 1 0.000685
Id 0 0.000000

3.删除和替换空值

删除某一列为NaN值的行,只要有一列是NaN,该行数据就会被删除

1
2
print(train_data.dropna(how='any'))

删除subset中某一列为NaN值的行,只要有一列是NaN,该行数据就会被删除

1
2
print(train_data.dropna(subset=['Fence', 'MiscFeature'], how='any'))

删除所有列都是NaN值的行

1
2
print(train_data.dropna(how='all'))

删除subset中所有列都是NaN值的行

1
2
print(train_data.dropna(subset=['Fence', 'MiscFeature'], how='all'))

其他

1
2
3
4
df.dropna(axis=1) #丢弃有缺失值的列
df.dropna(axis=1, how = 'all') #丢弃所有列中所有值均缺失的列
df.dropna(axis=0, subset=['name', 'age'])#丢弃name和age这两列中有缺失值的行

替换某列中的Nan值

1
2
3
train_data['Alley'].fillna(value='Not Found', inplace=True)
print(train_data)

替换None字符串

1
2
print(train_data.replace('None', np.nan))

替换字符串的时候,如果替换改变原数据的值

1
2
train_data.replace('None', np.nan, inplace=True)

4.缺失值填充

参考:数据转化

6.4 缺失值插补

也可以使用sklearn对特征的缺失值进行填充,方法有2种:

  • 单变量:对第 i 个特征中的缺失值只使用该特征的某些信息来进行填充(impute.SimpleImputer)
  • 多变量:对第 i 个特征中的缺失值使用整个数据集的信息来填充(impute.IterativeImputer)

数值型单变量缺失值填充

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np
from sklearn.impute import SimpleImputer

# 数值型单变量缺失值填充
imp = SimpleImputer(missing_values=np.nan, strategy='mean')
imp.fit([[1, 2], [np.nan, 3], [7, 6]])
>> SimpleImputer()

# 缺失值填充 (1+7)/2=4和(2+3+6)/3=3.66666667
X = [[np.nan, 2], [6, np.nan], [7, 6]]
print(imp.transform(X))
[[4. 2. ]
[6. 3.66666667]
[7. 6. ]]

标称型单变量缺失值填充

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import numpy as np
from sklearn.impute import SimpleImputer
import pandas as pd

# 标称型变量缺失值填充
df = pd.DataFrame([["a", "x"],
[np.nan, "y"],
["a", np.nan],
["b", "y"]], dtype="category")
# 使用出现次数最多的值来填充缺失值
imp = SimpleImputer(strategy="most_frequent")
print(imp.fit_transform(df))

[['a' 'x']
['a' 'y']
['a' 'y']
['b' 'y']]

多变量填充

多变量填充是使用全部数据建模的方式进行填充缺失值:含有缺失值的特征被视为 y,而其他特征当作 x,对 (x, y)拟合回归模型,然后利用这个模型来预测 y 中的缺失值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer

imp = IterativeImputer(max_iter=10, random_state=0)
imp.fit([[1, 2], [3, 6], [4, 8], [np.nan, 3], [7, np.nan]])
>> IterativeImputer(random_state=0)

# 拟合出第2个变量是第1个变量的2倍
X_test = [[np.nan, 2], [6, np.nan], [np.nan, 6]]
print(np.round(imp.transform(X_test)))

[[ 1. 2.]
[ 6. 12.]
[ 3. 6.]]

最近邻填充

全文 >>

go学习笔记——pprof性能分析工具

可以使用pprof来分析golang程序的CPU性能,内存占用,block死锁,Goroutine性能等,pprof一般是在需要分析代码性能的时候才加入

1.分析Gin web服务的性能

可以使用 gin-contrib/pprof 这个工具,参考:Gin框架中使用pprof

添加依赖

1
2
go get github.com/gin-contrib/pprof@v1.4.0

在gin的路由上添加 pprof.Register(app)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
"net/http"

"github.com/gin-contrib/pprof"
"github.com/gin-gonic/gin"
)

func main() {
app := gin.Default()

// 性能分析
pprof.Register(app)

app.GET("/test", func(c *gin.Context) {
c.String(http.StatusOK, "test")
})
app.Run(":3000")
}

启动web应用后访问如下path

1
2
http://localhost:3000/debug/pprof/

可以看到如下页面

使用go tool pprof命令采集20s的goroutine(Goroutine 是 Go 语言中的一种轻量级线程,提供了并发执行代码的能力)指标数据,如果不设置采集时间是默认采集30s,每10ms采集一次

1
2
go tool pprof --seconds 20 http://localhost:18080/debug/pprof/goroutine

采集完毕后可以直接输入 web 来可视化查看数据,不过需要提前安装graphviz,否则会报

全文 >>

Java多线程——其他工具类CyclicBarrier、CountDownLatch和Exchange

CyclicBarrier

适用于:创建一组任务,它们并行地执行任务,然后在进行下一个步骤之前等待,直至所有任务完成。它使得所有的并行任务都将在栅栏处列队,因此可以一致地向前移动。

表示大家彼此等待,大家集合好后才开始出发,分散活动后又在指定地点集合碰面,这就好比整个公司的人员利用周末时间集体郊游一样,先各自从家出发到公司集合后,再同时出发到公园游玩,在指定地点集合后再同时开始就餐…

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
package java_thread;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CyclicBarrierTest {

public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final CyclicBarrier cb = new CyclicBarrier(3);
for(int i=0;i<3;i++){
Runnable runnable = new Runnable(){
public void run(){
try {
Thread.sleep((long)(Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() +
"即将到达集合地点1,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));
cb.await();

Thread.sleep((long)(Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() +
"即将到达集合地点2,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));
cb.await();
Thread.sleep((long)(Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() +
"即将到达集合地点3,当前已有" + (cb.getNumberWaiting() + 1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));
cb.await();
} catch (Exception e) {
e.printStackTrace();
}
}
};
service.execute(runnable);
}
service.shutdown();
}
}

全文 >>

Java多线程——可阻塞的队列BlockingQueue

阻塞队列Semaphore有些相似,但也不同,阻塞队列一方存放数据,另一方释放数据,Semaphore通常则是由同一方设置和释放信号量。

ArrayBlockingQueue

  只有put方法和take方法才具有阻塞功能

用3个空间的队列来演示阻塞队列的功能和效果。

用两个具有1个空间的队列来实现同步通知的功能。

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
package java_thread;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class BlockingQueueTest {
public static void main(String[] args) {
final BlockingQueue queue = new ArrayBlockingQueue(3);
for(int i=0;i<2;i++){ //2个线程放数据
new Thread(){
public void run(){
while(true){
try {
Thread.sleep((long)(Math.random()*1000));
System.out.println(Thread.currentThread().getName() + "准备放数据!");
queue.put(1); //如果队列满的话,将在这里阻塞
System.out.println(Thread.currentThread().getName() + "已经放了数据," +
"队列目前有" + queue.size() + "个数据");
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}

}.start();
}

new Thread(){ //1个线程取数据
public void run(){
while(true){
try {
//将此处的睡眠时间分别改为100和1000,观察运行结果
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "准备取数据!");
queue.take(); //如果队列空的话,将在这里阻塞
System.out.println(Thread.currentThread().getName() + "已经取走数据," +
"队列目前有" + queue.size() + "个数据");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}.start();
}
}

全文 >>