XieJava's blog

记录最好的自己


  • 首页

  • 分类

  • 标签

  • 归档

  • 关于

pandas数据分析之排序和排名(sort和rank)

发表于 2022-01-30 | 更新于: 2025-04-08 | 分类于 技术 , 开发 | | 阅读次数:
字数统计: 2.1k | 阅读时长 ≈ 7

对数据集进行排序和排名的是常用最基础的数据分析手段,pandas提供了方便的排序和排名的方法,通过简单的语句和参数就可以实现常用的排序和排名。

本文以student数据集的DataFrame为例来演示和介绍pandas数据分析之排序和排名(sort和rank)。
数据集内容如下,包括学生的学号、姓名、年龄及语文、数学、英语的成绩:

1
2
3
4
import pandas as pd
import numpy as np
df = pd.read_excel('D:\\Python\\study\\pythontest\\pandastest\\数据集\\student.xlsx')
df

student数据集
数据集及源代码见:https://github.com/xiejava1018/pandastest.git

一、排序

对数据集进行排序是是常用的数据分析需求之一。pandas提供了按 索引标签排序sort_index()和按值排序sort_values()两种排序方法。对于DataFrame,可以根据任意一个轴上的索引标签进行排序。默认顺序排序,也可以设置按倒序排序。

1、按标签排序

1)按行标签索引排序

pandas默认按行标签索引顺序排序

1
2
#按行索引排序
df.sort_index()

按行索引排序
可以通过设置ascending=False参数进行倒序排序

1
2
#按行索引倒序排序
df.sort_index(ascending=False)

按行索引倒序排序

2)按列标签索引排序

通过给 axis 轴参数传递 0 或 1,可以对列标签进行排序。默认情况下,axis=0 表示按行排序;而 axis=1 则表示按列排序。

1
2
#按列索引排序
df.sort_index(axis=1)

按列索引排序
同样可以设置ascending=False参数进行倒序排序

1
2
#按列索引倒序排序
df.sort_index(axis=1,ascending=False)

按列索引倒序排序

2、按值排序

在实际应用中用得最多的应该是根据某一列的值进行排序。在pandas中可以通过sort_value(),在sort_value中可以设定按某个列排序,也可以通过sort_value(by=[]),通过设置by=[‘a’,’b’]列表来指定多个需要排序的列。

1)对单个列的值排序

如在数据集中对语文成绩进行排序。

1
2
#按语文成绩排序
df.sort_values('4-语文')

对语文成绩进行排序

2)对多个列的值进行排序

通过设置by=[‘a’,’b’]列表来指定多个需要排序的列。
如对数据集中的语文和数学进行排序

1
2
#按语文、数学排序
df.sort_values(by=['4-语文','5-数学'])

对数据集中的语文和数学进行排序

3、排序算法

sort_values() 提供了参数kind用来指定排序算法。这里有三种排序算法:

  • mergesort(归并排序)
  • heapsort(堆排序)
  • quicksort(快速排序)

默认为 quicksort(快速排序) ,其中 mergesort归并排序是最稳定的算法。
具体用法如下:

1
2
#按语文、数学用mergesort归并排序算法排序
df.sort_values(by=['4-语文','5-数学'],kind='mergesort')

排序算法

二、排名

排名和排序的区别在于排序一定是有顺序,而排名分先后并列。如在现实生活中相同的分数存在排名并列的情况。
在《使用python进行数据分析》一书中对rank排名的描述为:排名是指对数组从1到有效数据点总数分配名次的操作。Series和DataFrame的rank方法是实现排名的方法,默认情况下,rank是通过“为各组分配一个平均排名”的方式破坏平级关系。这段话讲得是什么鬼?其实就是在存在并列排名的时候采用一定的策略来打破这种关系。
排名中的平级关系打破方法有如下几种:

method 说明
average 默认:在每个组中分配平均排名
min 对整个组使用最小排名
max 对整个组使用最大排名
first 按照值在数据中出现的次序分配排名
dense 类似于method=’min’,但组件排名总是加1,而不是一个组中的相等元素的数量

rank()函数原型:rank(axis=0, method: str = 'average', numeric_only: Union[bool, NoneType] = None, na_option: str = 'keep', ascending: bool = True, pct: bool = False)
这里method取值可以为’average’,’first’,’min’, ‘max’,’dense’,用来打破排名中的平级关系的。
光看这些说明还是比较难理解。下面通过实例来说明:

1、默认average 排名

在数据集中我们只取“学号”、“姓名”、“语文”,然后取“语文”的排名,默认average

1
2
3
4
df_rank=df[['1-学号','2-姓名','4-语文']].copy()
#按语文成绩进行rank的默认排名
df_rank['语文排名']=df_rank['4-语文'].rank(ascending=False)
df_rank.sort_values(by='语文排名')

默认average 排名

这个排名很奇怪,97分排名第一没有问题,居然没有第二名,三个96分排名均为3,还有两个90分排名为9.5。这是什么鬼?
原来这就是默认的“average”规则,成绩相同时,取顺序排名中所有名次之和除以该成绩的个数,如两个90分的名次为最后两名分别为9名和10名,即(9+10)/2=9.5,三个96分的名次分别为2、3、4 那么排名为(2+3+4)/3=9/3=3

2、mothod=’min’的排名

1
2
3
#按语文成绩进行min排名
df_rank['语文排名']=df_rank['4-语文'].rank(method='min',ascending=False)
df_rank.sort_values(by='语文排名')

按语文成绩进行min排名

在这个排名中看到有3个并列为2的排名,但没有排名为3、4的,有两个排名为9的,但没有排名为10的。可以看出当method=“min”时,成绩相同的同学,取在顺序排名中最小的那个排名作为该值的排名,张三、王五、顾十三个同学都是96分排名分别为2、3、4,那么当method为min时,取2、3、4的最小的那个作为成绩为96的整体排名即第2名。因为有了三个2名,接下来就从5名开始,5、6、7、8,到了第9名又有两个同分数的取9、10的最小排名为9,所以有两个9名。

3、mothod=’max’的排名

1
2
3
#按语文成绩进行max排名
df_rank['语文排名']=df_rank['4-语文'].rank(method='max',ascending=False)
df_rank.sort_values(by='语文排名')

按语文成绩进行max排名
与min相反,成绩相同的同学,排名相同取顺序最大的排名,张三、王五、顾十三个同学都是96分排名分别为2、3、4,那么当method为min时,取2、3、4的最小的那个作为成绩为96的整体排名即第2名。当method为max时,取最大的4作为96分的整体排名,同理90分的取10为90分的整体排名。

4、mothod=’first’的排名

1
2
3
#按语文成绩进行first排名
df_rank['语文排名']=df_rank['4-语文'].rank(method='first',ascending=False)
df_rank.sort_values(by='语文排名')

按语文成绩进行first排名

first排名很好理解了,有点先到先得的意思,成绩相同,谁的索引排前,谁的排名就靠前,比如张三、王五、顾十 这三个同学都是96分,按理应该是并列第2,但张三的索引比王五和顾十的都靠前,王五的索引比顾十靠前,所以他们的顺序分别为2、3、4,同理陈一、钱七的分数都是90分,但陈一的索引比钱七靠前所以陈一排名为9、钱七排名第10

5、mothod=’dense’的排名

1
2
3
#按语文成绩进行dense排名
df_rank['语文排名']=df_rank['4-语文'].rank(method='dense',ascending=False)
df_rank.sort_values(by='语文排名')

按语文成绩进行dense排名
“dense”: 是密集的意思,也比较好理解,即相同成绩的同学排名相同,其他依次加1即可。可以看到张三、王五、顾十这三位同学都是96分,并列排名第2,后面的加1,即比他们分数稍低的赵六95分排名第3,后面依次。

6、不同method的排名对比

最后不同method的排名对比:

1
2
3
4
5
6
7
8
9
10
11
#按语文成绩进行rank的默认排名
df_rank['语文排名-average']=df_rank['4-语文'].rank(ascending=False)
#按语文成绩进行min排名
df_rank['语文排名-min']=df_rank['4-语文'].rank(method='min',ascending=False)
#按语文成绩进行max排名
df_rank['语文排名-max']=df_rank['4-语文'].rank(method='max',ascending=False)
#按语文成绩进行first排名
df_rank['语文排名-first']=df_rank['4-语文'].rank(method='first',ascending=False)
#按语文成绩进行dense排名
df_rank['语文排名-dense']=df_rank['4-语文'].rank(method='dense',ascending=False)
df_rank.sort_values(by='4-语文',ascending=False)

按语文成绩进行rank的默认排名

数据集及源代码见:https://github.com/xiejava1018/pandastest.git


作者博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

pandas数据结构(Series和DataFrame)

发表于 2022-01-23 | 更新于: 2025-04-08 | 分类于 技术 , 开发 | | 阅读次数:
字数统计: 2.9k | 阅读时长 ≈ 11

简介

无可非议,pandas是Python最强大的数据分析和探索工具之一,因金融数据分析工具而开发,支持类似于SQL语句的模型,可以对数据进行增删改查等操作,支持时间序列分析,也能够灵活的处理缺失的数据。它含有使数据分析工作变得更快更简单的高级数据结构和操作工具。pandas是基于NumPy构建的,让以NumPy为中心的应用变得更加简单。

这里所说的让pandas变得更快更简单的高级数据结构就是Series和DataFrame。要熟练使用pandas,首先得要熟悉它的这两个主要的数据结构:Series和DateFrame。

本文将针对Series和DateFrame,介绍Series和DataFrame数据对象的创建及基于数据对象的基础上对数据进行选择、增加、删除等数据操作。

一、Series

Series是一种类似于一维数组对象,它是由一组的数据值value(各种NumPy数据类型)以及一组与之相关的数据标签index(即索引)组成,其中标签与数据值之间是一一对应的关系。

1
2
3
import pandas as pd
obj = pd.Series(['陈一','周二','张三','李四','王五','赵六','钱七','孙八','何九','顾十'])
obj

结果:

1
2
3
4
5
6
7
8
9
10
11
0    陈一
1 周二
2 张三
3 李四
4 王五
5 赵六
6 钱七
7 孙八
8 何九
9 顾十
dtype: object

Series的字符串表现形式为:索引在左边,值在右边。由于没有为数据指定索引,于是会自动创建一个0到N-1(N为数据的长度)的整数型索引。
Serires数据结构

可以通过Series的values和index属性获取其数组表示形式和索引对象。
通过Series的values和index属性获取其数组表示形式和索引对象

可以将Series看成一个定长的有序字典,因为它是索引值到数据值的一个映射。

1、Series对象创建

pandas 使用 Series() 函数来创建 Series 对象,通过这个对象可以调用相应的方法和属性,从而达到处理数据的目的:

1
2
import pandas as pd
obj=pd.Series( data, index, dtype, copy)

参数说明如下:

参数名称 描述
data 输入的数据,可以是列表、常量、ndarray 数组等。
index 索引值必须是惟一的,如果没有传递索引,则默认为 np.arrange(n)。
dtype dtype表示数据类型,如果没有提供,则会自动判断得出。
copy 表示对 data 进行拷贝,默认为 False。

data可以是列表、常量、ndarray数组等,如果数据被存放在一个Python字典dict中,也可以直接通过这个dict来创建Series,如果没有传入索引时会按照字典的键来构造索引;反之,当传递了索引时需要将索引标签与字典中的值一一对应。
前面的列子是通过列表来创建的Series,接下来看下通过ndarray和dic来创建Series。

通过ndarray创建Series

1
2
3
4
5
6
#ndarray创建Series
import pandas as pd
import numpy as np
data=np.array(['陈一','周二','张三','李四','王五','赵六','钱七','孙八','何九','顾十'])
obj= pd.Series(data)
print(obj)

结果:

1
2
3
4
5
6
7
8
9
10
11
0    陈一
1 周二
2 张三
3 李四
4 王五
5 赵六
6 钱七
7 孙八
8 何九
9 顾十
dtype: object

通过dict创建Series

#通过dict创建Series,没有设置indx

1
2
3
4
import pandas as pd
data = {'1' :'张三', '2' :'李四', '3' : '王五'}
obj=pd.Series(data)
print(obj)

结果:

1
2
3
4
1    张三
2 李四
3 王五
dtype: object

当传递的索引值无法找到与其对应的值时,使用 NaN(非数字)填充。

1
2
3
4
5
6
#通过dict创建Series,设置indx
import pandas as pd
data = {'1' :'张三', '2' :'李四', '3' : '王五'}
obj=pd.Series(data,index=['1','2','4'])
#索引4没有在dict的对应的key,所以使用NaN(非数字)填充
print(obj)

结果:

1
2
3
4
1     张三
2 李四
4 NaN
dtype: object

2、Series操作

Series数据访问

Series提供了多种数据访问的方式,可以通过位置下标及索引来访问数据,可以访问单个数据也可以访问多个数据。

通过位置下标及索引来访问数据

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
import pandas as pd
import numpy as np
data=np.array(['陈一','周二','张三','李四','王五','赵六'])
obj= pd.Series(data,index=['一','二','三','四','五','六'])
print('obj的Series数据')
print(obj)
print('\n')
#位置下标访问
print('位置下标访问:obj[0]')
print(obj[0])
print('\n')
#切片访问
print('位置切片访问多个元素值:obj[1:3]')
print(obj[1:3])
print('\n')
#索引访问
print('索引访问:obj[obj.index==\'三\']')
print(obj[obj.index=='三'])
print('\n')
#索引访问
print('索引访问:obj[\'一\']')
print(obj['一'])
print('\n')
#索引列表访问
print('索引列表访问多个元素值:obj[[\'二\',\'三\']]')
print(obj[['二','三']])
print('\n')

结果:

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
obj的Series数据
一 陈一
二 周二
三 张三
四 李四
五 王五
六 赵六
dtype: object

位置下标访问:obj[0]
陈一

位置切片访问多个元素值:obj[1:3]
二 周二
三 张三
dtype: object

索引访问:obj[obj.index=='三']
三 张三
dtype: object

索引访问:obj['一']
陈一

索引列表访问多个元素值:obj[['二','三']]
二 周二
三 张三
dtype: object

head()&tail()查看数据

如果想要查看 Series 的某一部分数据,可以使用 head() 或者 tail() 方法。其中 head() 返回前 n 行数据,默认显示前 5 行数据。

1
2
3
4
5
6
7
8
9
10
11
12
import pandas as pd
import numpy as np
data=np.array(['陈一','周二','张三','李四','王五','赵六'])
obj= pd.Series(data,index=['一','二','三','四','五','六'])
#输出前三行数据
print('输出前三行数据')
print(obj.head(3))
print('\n')
#输出后两行数据
print('输出后两行数据')
print(obj.tail(2))
print('\n')

结果:

1
2
3
4
5
6
7
8
9
10
输出前三行数据
一 陈一
二 周二
三 张三
dtype: object

输出后两行数据
五 王五
六 赵六
dtype: object

Series数据增加

1.直接通过索引增加

1
2
3
4
5
6
7
8
9
10
11
12
#通过索引增加数据
obj['十一']='肖十一'
print(obj)

一 陈一
二 周二
三 张三
四 李四
五 王五
六 赵六
十一 肖十一
dtype: object

2.通过append()增加

1
2
3
4
#通过append()增加多个数据
obj2=pd.Series(['郭芙蓉','杨过'],index=['十二','十三'])
obj=obj.append(obj2)
print(obj)

结果:

1
2
3
4
5
6
7
8
9
10
一      陈一
二 周二
三 张三
四 李四
五 王五
六 赵六
十一 肖十一
十二 郭芙蓉
十三 杨过
dtype: object

Series数据修改

Series数据可以通过制定索引直接修改
如:修改索引为十一的数据,直接obj[‘十一’]=’肖XX’,就可以进行修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#修改Series数据
obj['十一']='肖XX'
print(obj)

一 陈一
二 周二
三 张三
四 李四
五 王五
六 赵六
十一 肖XX
十二 郭芙蓉
十三 杨过
dtype: object

Series数据删除

通过drop()删除,注意如果没有带inplace=True,会返回一个新的Series对象。如果要修改本对象,注意要带上inplace=True。

1.删除单个数据

1
2
3
4
5
6
7
8
9
10
11
12
obj.drop('十一',inplace=True)
print(obj)

一 陈一
二 周二
三 张三
四 李四
五 王五
六 赵六
十二 郭芙蓉
十三 杨过
dtype: object

2.删除多个数据

参数为索引列表,即可以删除索引为列表中的数据

1
2
3
4
5
6
7
8
9
10
obj.drop(['十二','十三'],inplace=True)
print(obj)

一 陈一
二 周二
三 张三
四 李四
五 王五
六 赵六
dtype: object

二、DataFrame

DataFrame 是 Pandas 的重要数据结构之一,也是在使用 Pandas 进行数据分析过程中最常用的结构之一。DataFrame 一个表格型的数据结构,既有行标签(index),又有列标签(columns),它也被称异构数据表,所谓异构,指的是表格中每列的数据类型可以不同,比如可以是字符串、整型或者浮点型等。DataFrame 的每一行数据都可以看成一个 Series 结构,只不过,DataFrame 为这些行中每个数据值增加了一个列标签。因此 DataFrame 其实是从 Series 的基础上演变而来。可以把DataFrame看做是关系型数据库里或Excel里的一张表格来理解。
DataFrame数据结构
DataFrame 数据结构的特点:
DataFrame 每一列的标签值允许使用不同的数据类型;
DataFrame 是表格型的数据结构,具有行和列;
DataFrame 中的每个数据值都可以被修改。
DataFrame 结构的行数、列数允许增加或者删除;
DataFrame 有两个方向的标签轴,分别是行标签和列标签;
DataFrame 可以对行和列执行算术运算。

1、DataFrame对象的创建

1
2
import pandas as pd
df=pd.DataFrame( data, index, columns, dtype, copy)

参数说明:

参数名称 说明
data 输入的数据,可以是 ndarray,series,list,dict,标量以及一个 DataFrame。
index 行标签,如果没有传递 index 值,则默认行标签是 np.arange(n),n 代表 data 的元素个数。
columns 列标签,如果没有传递 columns 值,则默认列标签是 np.arange(n)。
dtype dtype表示每一列的数据类型。
copy 默认为 False,表示复制数据 data。

Pandas 提供了多种创建 DataFrame 对象的方式可以看data的参数说明,包括列表、ndarray、series、dict等。
平时在数据分析过程中用得最多的应该是从其他数据源文件如cvs、excel、数据库、WEBAPI等方式加载数据到DataFrame中。
如:从Excel中加载数据。更多的数据加载方式见:http://xiejava.ishareread.com/posts/4864590d/

1
2
3
import pandas as pd
df = pd.read_excel('D:\\Python\\study\\pythontest\\pandastest\\数据集\\staff.xlsx')
df

staff数据集

2、DataFrame数据操作

DataFrame 可以使用行索引(index )来选取 DataFrame 中的数据并进行操作。也可以使用列索(columns )引来完成数据的选取、添加和删除操作。

1) 行索引操作DataFrame

选取数据

行标签选取数据

1
2
#选取行标签为2的行
df.loc[[2]]

选取行标签为2的行
注意:如果是df.loc[2],同样是选择行标签为2的行,但现实效果为
选取行标签为2的行
因为df.loc[2]返回是Series对象,而df.loc[[2]]返回的是DataFrame对象

1
2
type(df.iloc[2])
pandas.core.series.Series
1
2
type(df.loc[[2]])
pandas.core.frame.DataFrame

切片选取数据

1
2
#切片选取数据(左闭右开)
df[2:4]

切片选取数据

增加行

添加数据行,使用 append() 函数,可以将新的数据行添加到 DataFrame 中,该函数会在行末追加数据行。

1
2
3
df_1 = pd.DataFrame([[11,'肖十一','30','女','7000','1'],[12,'郭芙蓉','30','女','7400','1']],index=[11,12],columns = ['staff_id','staff_name','staff_age','staff_gender','staff_salary','staff_depatment_id'])
df=df.append(df_1)
df

 添加数据行

注意新增加的DataFrame如果没有指定行索引,将会默认从0开始,添加数据行后将会有行重复的行索引。如没有指定index=[11,12]

1
2
3
df_1 = pd.DataFrame([[11,'肖十一','30','女','7000','1'],[12,'郭芙蓉','30','女','7400','1']],columns = ['staff_id','staff_name','staff_age','staff_gender','staff_salary','staff_depatment_id'])
df=df.append(df_1)
df

添加数据行有重复行索引

删除行

可以使用行索引标签,从 DataFrame 中删除某一行数据。如果索引标签存在重复,那么它们将被一起删除

1
2
df=df.drop(0)
df

可以看到到行索引为0的两条记录被一起删除了。
删除

2) 列索引操作DataFrame

列索引选取数据列

通过指定列索引来选取数据列,如选择只显示staff_id,staff_name,staff_gender三列

1
2
df2=df[['staff_id','staff_name','staff_gender']]
df2

列索引选取数据列

列索引添加数据列

1
2
3
4
df3=df['staff_salary']+500
#在df的基础上增加append_cloume列,新增的append_cloume列为df['staff_salary']+500,即薪水加了500的列
df['append_cloume']=df3
df

列索引添加数据列

列索引删除数据列

通过del 来删除指定的数据列,如删除staff_depatment_id列

1
2
del df['staff_depatment_id']
df

列索引删除数据列

本文介绍了pandas的两大核心数据结构Series和DataFrame,分别介绍了Series和DataFrame数据对象的创建及基于数据对象的基础上对数据进行选择、增加、删除等数据操作,可以加深对Series和DataFrame的理解,并可以将创建,增、删、改、查等应用于实际的数据处理应用中。


作者博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

pandas数据加载(csv、excel、json、mysql、webAPI)

发表于 2022-01-22 | 更新于: 2025-04-08 | 分类于 技术 , 开发 | | 阅读次数:
字数统计: 1.4k | 阅读时长 ≈ 5

pandas
pandas 是基于NumPy 的一种工具,该工具是为解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。Pandas的名称来自于面板数据(panel data)和python数据分析(data analysis)。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。它是使Python成为强大而高效的数据分析环境的重要因素之一。

数据的输入是数据分析的第一步,如果不能将数据快速方便的导入导出python,那么pandas不可能成为强大而高效的数据分析环境,本文重点介绍pandas的数据输入加载。pandas的数据输入可以划分为几个大类:读取文本文件和其他更高效的磁盘存储格式,加载数据库中的数据,利用Web API获取网络资源。
pandas数据处理
pandas的IO工具支持非常多的数据输入输出方式。包括csv、json、Excel、数据库等。

Format Type Data Description Reader Writer
text CSV read_csv to_csv
text JSON read_json to_json
text HTML read_html to_html
text Local clipboard read_clipboard to_clipboard
binary MS Excel read_excel to_excel
binary OpenDocument read_excel
binary HDF5 Format read_hdf to_hdf
binary Feather Format read_feather to_feather
binary Parquet Format read_parquet to_parquet
binary Msgpack read_msgpack to_msgpack
binary Stata read_stata to_stata
binary SAS read_sas
binary Python Pickle Format read_pickle to_pickle
SQL SQL read_sql to_sql
SQL Google Big Query read_gbq to_gbq

本文通过几个实例,介绍几种常用的数据加载方式,包括从csv文件、excel文件、关系型数据库如mysql、API接口加载json数据,来初步体验一下pandas加载数据的便捷性。

见上表pandas 提供了多种数据源读取数据的方法:
read_csv() 用于读取文本文件
read_json() 用于读取 json 文件
read_sql_query() 读取 sql 语句查询的表记录

一、读取CSV文件

CSV 又称逗号分隔值文件,是一种简单的文件格式,以特定的结构来排列表格数据。 CSV 文件能够以纯文本形式存储表格数据,比如电子表格、数据库文件,并具有数据交换的通用格式。CSV 文件会在 Excel 文件中被打开,其行和列都定义了标准的数据格式。
将 CSV 中的数据转换为 DataFrame 对象是非常便捷的。和一般文件读写不一样,它不需要你做打开文件、读取文件、关闭文件等操作。相反,只需要一行代码就可以完成上述所有步骤,并将数据存储在 DataFrame 中。
pandas通过read_csv()从 CSV 文件中读取数据,并创建 DataFrame 对象。
下面通过一个实例来说明。一个用于测试的员工数据集csv的数据如下,文件为staff.csv。

1
2
3
4
5
6
7
8
9
10
11
"staff_id","staff_name","staff_age","staff_gender","staff_salary","staff_depatment_id"
"1","陈一","30","男","7000","1"
"2","周二","31","男","12000","2"
"3","张三","30","女","13000","3"
"4","李四","29","女","15000","1"
"5","王五","29","男","9000","2"
"6","赵六","35","男","8600","1"
"7","钱七","36","女","9700","3"
"8","孙八","40","女","10000","3"
"9","何九","40","男","11000","1"
"10","顾十","37","女","15000","2"

代码如下:

1
2
3
import pandas as pd
df = pd.read_csv('C:\\Users\\xiejava\\Desktop\\staff.csv')
df

输出:
通过csv加载

二、读取EXCEL文件

Excel 是由微软公司开发的办公软件之一,它在日常工作中得到了广泛的应用。在数据量较少的情况下,Excel 对于数据的处理、分析、可视化有其独特的优势,因此可以显著提升您的工作效率。但是,当数据量非常大时,Excel 的劣势就暴露出来了,比如,操作重复、数据分析难等问题。Pandas 提供了操作 Excel 文件的函数,可以很方便地处理 Excel 表格。
pandas提供了 read_excel() 方法,从 Excel文件中读取数据,并创建 DataFrame 对象。
staff数据集excel文件staff.xlsx如下图:
staff.xlsx
代码如下:

1
2
3
import pandas as pd
df = pd.read_excel('C:\\Users\\xiejava\\Desktop\\staff.xlsx')
df

输出:
通过Excel加载数据

三、读取MySQL数据库表

在许多应用中,数据很少取自文本文件,因为这种方式存储数据量有限且比较低效。最常见的是基于SQL的关系型数据库如MySQL、MS-SQL、PostgreSQL等。pandas将关系型数据库加载到DataFrame的过程很简单,通过read_sql_query()方法就可以快速的将数据加载。
同样是staff的数据集,在mysql中的表结构如下:

1
2
3
4
5
6
7
8
CREATE TABLE `staff` (
`staff_id` int(11) DEFAULT NULL,
`staff_name` varchar(64) DEFAULT NULL,
`staff_age` int(2) DEFAULT NULL COMMENT '年龄',
`staff_gender` varchar(2) DEFAULT NULL COMMENT '性别',
`staff_salary` double DEFAULT NULL COMMENT '薪水',
`staff_depatment_id` int(2) DEFAULT NULL COMMENT '部门ID'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

数据如下:
staff数据集MySQL记录
代码如下:

1
2
3
4
5
6
import pandas as pd
from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://root:yourpassword@localhost:3306/pandastest')
sql_query_staff = 'select * from staff;'
df_staff = pd.read_sql_query(sql_query_staff, engine)
df_staff

输出:
加载mysql数据

四、读取Web API的数据

除了本地文件和数据库外,许多网站和web应用都有一些通过JSON或其他格式提供数据的公共API。可以通过Python的requests包来访问这些API获得相应的数据,经过解析处理后加载到pandas的DataFrame中。
为了演示方便,本文通过Flask做了一个staff数据集的API,效果如下:
staff数据集API
通过requests包来访问API,通过json包来解析json,然后加载到pandas的DataFrame中。
代码如下:

1
2
3
4
5
6
7
8
import requests
import json
import pandas as pd
url='http://127.0.0.1:5000/getstaff'
resp=requests.get(url)
data=json.loads(resp.text)
staff=pd.DataFrame(data)
staff

输出:
加载WEBAPI数据

至此,通过staff测试数据集介绍了pandas的常用多种类型数据源的加载,包括csv、excel、mysql、web API。可以看出pandas对于数据加载非常的方便高效。

全部数据集及源代码:https://github.com/xiejava1018/pandastest.git


作者博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

Python实现读取Word表格计算汇总写入Excel

发表于 2022-01-20 | 更新于: 2025-04-08 | 分类于 技术 , 开发 | | 阅读次数:
字数统计: 1.4k | 阅读时长 ≈ 6

快过年了,又到了公司年底评级的时候了。今年的评级和往常一下,每个人都要填写公司的民主评议表,给各个同事进行评价打分,然后部门收集起来根据收集上来的评价表进行汇总统计。想想要收集几十号人的评价表,并根据每个人的评价表又要填到Excel中进行汇总计算统计给出每个人的评价,就头大。虽然不是个什么难事,但是是个无脑的细致活。几十个人的评价也得要花大半天的时间来弄,而且搞多了还容易搞错。如是就想起干脆用Python写个小程序自动来处理这些脏活累活,评级年年都要评,每年都可以用。

要做的事情就是读放到某个文件夹中的word文档中的评价表格,根据表格内容进行处理,然后汇总所有的表格数据,根据计算规则,算出每个人的评分,在根据评分计算每个人的评价。汇总后写入Excel中。
处理Word解析、汇总、统计写入Excel

不可否认用Python来实现这样的事情真的是太方便了,人生苦短我用Python。
我是用的python的docx包来处理word,用pandas来处理数据并写入excel

一、首先导入包

1
2
pip install docx
pip install pandas

pandas写excel依赖openpyxl包所以也到导入

1
pip install openpyxl

二、读评价表所在的目录文件

通过python的os包,列出文件夹里面的文件,识别出.docx的文件

1
2
3
4
files=os.listdir(filepah)
for file in files:
if file.find('.docx')>0:
docfilepah=filepah+file

三、读word文件,处理word中的表格数据

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
data=[]
#读word的docx评议表文件,并读取word中的表格数据
def procdoc(docfilepath):
document=Document(docfilepath)
tables=document.tables
table=tables[0]
for i in range(1,len(table.rows)):
id=int(table.cell(i,0).text)
name=table.cell(i,1).text
excellent=0
if table.cell(i,2).text!='' and table.cell(i,2).text is not None:
excellent=1
competent = 0
if table.cell(i, 3).text!='' and table.cell(i, 3).text is not None:
competent=1
basicacompetent=0
if table.cell(i, 4).text!='' and table.cell(i, 4).text is not None:
basicacompetent=1
notcompetent = 0
if table.cell(i, 5).text!='' and table.cell(i, 5).text is not None:
notcompetent=1
dontunderstand =0
if table.cell(i, 6).text!='' and table.cell(i, 6).text is not None:
dontunderstand=1
appraisedata=[id,name,excellent,competent,basicacompetent,notcompetent,dontunderstand]
data.append(appraisedata)

四、统计计算

通过pandas直接对数据进行统计计算,避免了传统的循环计算。

1
2
3
4
5
df = pd.DataFrame(data,columns=['序号','姓名','优秀','称职','基本称职','不称职','不了解'])
df=df.groupby(['序号','姓名']).sum() #汇总每个人每一项的评分
df['票数'] = df.apply(lambda x: x.sum(), axis=1) #统计票数
df['计分'] = (df['优秀']*95+df['称职']*85+df['基本称职']*75+df['不称职']*65+df['不了解']*0)/len(df)#根据规则计分
df['评价']=df['计分'].map(getscore) #根据规则评价评级

计分方法:民主评议得分=Σ各等级票数*等级计分分数/总票数,其中“优秀”计95分,“称职”计85分,“基本称职”计75分,“不称职”计65分,“不了解”不计分。

1
2
3
4
5
6
7
8
9
10
11
#根据评分规则计算评级
def getscore(x):
if x>=95:
score='优秀'
elif x>=80 and x<95:
score='称职'
elif x>=75 and x<80:
score='基本称职'
elif x<75:
score='不称职'
return score

五、将统计计算结果写入汇总Excel

通过pandas直接可以将dataframe写入到Excel文件

1
2
3
4
5
6
#将汇总计算好的数据写入Excel
def write2excle(exclefile,dataframe):
writer = pd.ExcelWriter(exclefile)
dataframe.to_excel(writer)
writer.save()
print('输出成功')

完整代码

Python不到八十行代码,实现读Word->处理表格数据->汇总计算数据->写Excel。
完整的代码如下:

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
import os
import pandas as pd
from docx import Document

data=[]
#读word的docx评议表文件,并读取word中的表格数据
def procdoc(docfilepath):
document=Document(docfilepath)
tables=document.tables
table=tables[0]
for i in range(1,len(table.rows)):
id=int(table.cell(i,0).text)
name=table.cell(i,1).text
excellent=0
if table.cell(i,2).text!='' and table.cell(i,2).text is not None:
excellent=1
competent = 0
if table.cell(i, 3).text!='' and table.cell(i, 3).text is not None:
competent=1
basicacompetent=0
if table.cell(i, 4).text!='' and table.cell(i, 4).text is not None:
basicacompetent=1
notcompetent = 0
if table.cell(i, 5).text!='' and table.cell(i, 5).text is not None:
notcompetent=1
dontunderstand =0
if table.cell(i, 6).text!='' and table.cell(i, 6).text is not None:
dontunderstand=1
appraisedata=[id,name,excellent,competent,basicacompetent,notcompetent,dontunderstand]
data.append(appraisedata)

#读取评议表的目录,并处理目录中的docx文件,根据评议表计算评分,写入汇总表。
def readfile(filepah):
files=os.listdir(filepah)
for file in files:
if file.find('.docx')>0:
docfilepah=filepah+file
procdoc(docfilepah)
df = pd.DataFrame(data,columns=['序号','姓名','优秀','称职','基本称职','不称职','不了解'])
print(df)
df=df.groupby(['序号','姓名']).sum()
df['票数'] = df.apply(lambda x: x.sum(), axis=1)
df['计分'] = (df['优秀']*95+df['称职']*85+df['基本称职']*75+df['不称职']*65+df['不了解']*0)/len(df)
df['评价']=df['计分'].map(getscore)
print(df)
write2excle('民主评议\\民主评议表汇总.xlsx',df)

#根据评分规则计算评级
def getscore(x):
if x>=95:
score='优秀'
elif x>=80 and x<95:
score='称职'
elif x>=75 and x<80:
score='基本称职'
elif x<75:
score='不称职'
return score

#将汇总计算好的数据写入Excel
def write2excle(exclefile,dataframe):
writer = pd.ExcelWriter(exclefile)
dataframe.to_excel(writer)
writer.save()
print('输出成功')

if __name__ == '__main__':
readfile('民主评议\\')

全部源代码:https://github.com/xiejava1018/pythonprocword

作者博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

网络安全之恶意代码

发表于 2022-01-17 | 更新于: 2025-04-08 | 分类于 技术 , 网络安全 | | 阅读次数:
字数统计: 3k | 阅读时长 ≈ 10

恶意代码是一种有害的计算机代码或 web 脚本,其设计目的是创建系统漏洞,并借以造成后门、安全隐患、信息和数据盗窃、以及其他对文件和计算机系统的潜在破坏。恶意代码不仅使企业和用户蒙受了巨大的经济损失,而且使国家的安全面临着严重威胁。1991年的海湾战争是美国第一次公开在实战中使用恶意代码攻击技术取得重大军事利益,从此恶意代码攻击成为信息战、网络战最重要的入侵手段之一。恶意代码问题无论从政治上、经济上、还是军事上,都成为信息安全面临的首要问题。让我们一起来认识一下恶意代码。

一、什么是恶意代码

恶意代码(Unwanted Code)是指故意编制或设置的、对网络或系统会产生威胁或潜在威胁的计算机代码。最常见的恶意代码有计算机病毒(简称病毒)、特洛伊木马(简称木马)、计算机蠕虫(简称蠕虫)、后门、逻辑炸弹等。

二、恶意代码的分类

1、恶意代码分类

恶意代码的分类标准主要是代码的独立性和自我复制性,独立的恶意代码是指具备一个完整程序所应该具有的全部功能功能,能够独立传播、运行的恶意代码,这样的恶意代码不需要寄宿在另一个程序中。非独立恶意代码只是一段代码,必须嵌入某个完整的程序中,作为该程序的一个组成部分进行传播和运行。对于非独立恶意代码,自我复制过程就是将自身嵌入宿主程序的过程,这个过程也称为感染宿主程序的过程。对于独立恶意代码,自我复制过程就是将自身传播给其他系统的过程。不具有自我复制能力的恶意代码必须借助其他媒介进行传播。

分类:

类别 实例
具有自我复制能力的依附性恶意代码 主要代表是病毒
具有自我复制能力的独立性恶意代码 主要代表是蠕虫
不具有自我复制能力的依附性恶意代码 主要代表是后门
不具有自我复制能力的独立性恶意代码 主要代表是木马

2、不同恶意代码的区别

病毒侧重于破坏系统和程序的能力

木马侧重于窃取敏感信息的能力

蠕虫侧重于网络中的自我复制能力和自我传染能力

病毒 木马 蠕虫
存在形式 寄生 独立文件 独立文件
传染途径 通过宿主程序运行 植入目标主机 系统漏洞
传染速度 慢 最慢 快
攻击目标 本地文件 文件、网络主机 存在漏洞的网络程序
触发机制 攻击者指定条件 自启动 自动攻击有漏洞的程序
防范方法 从宿主文件中清除 清除启动项和木马服务程序 更新安全补丁
对抗主体 用户,反病毒软件 用户、管理员、反病毒软件 应用程序供应商、用户和管理员

三、恶意代码基本技术

1、隐蔽技术

(1)本地隐藏

防止本地系统管理人员觉察而采取的隐蔽手段。

  • 文件隐蔽:将恶意代码的文件命名为与系统的合法程序文件名相似的名称,或者干脆取而代之,或者将恶意代码文件附加到合法程序文件中。
  • 进程隐蔽:附着或替换系统进程,使恶意代码以合法服务的身份运行,从而隐蔽恶意代码。还可以通过修改进程列表程序,修改命令行参数使恶意代码进程的信息无法查询。也可以借助RootKit 技术实现进程隐蔽。
  • 网络连接隐蔽:借用现有服务的端口实现网络连接隐蔽,如使用80端口,攻击者在自己的数据包设置特殊标识,通过标识识别连接信息,未标识的WWW 服务网络包仍转交给原服务程序处理。
  • 编译器隐蔽:由编译器在对程序代码进行编译时植入恶意代码,从而实现恶意代码在用户程序中的隐藏和原始分发攻击。恶意代码的植入者是编译器开发人员。
  • RootKit隐蔽:利用适当的Rootkit工具,可以很好的隐蔽自身或指定的文件、进程和网络连接等,很难被管理员发现。

    (2)网络隐藏

    网络隐藏主要是指通信内容和传输通道的隐藏。
  • 通信内容隐蔽:使用加密算法对所传输的内容进行加密能够隐蔽通信内容。
  • 传输通道隐藏:利用隐蔽通道技术,实现对传输通道的隐蔽。(隐蔽通道(Covert Channel)是一个不受安全机制控制的、利用共享资源作为通信通路的信息流。包括有:存储隐蔽通道和时间隐蔽通道。)

2、生存技术

恶意代码的生存技术主要包括四种类型:

  • 反跟踪技术:通过提高恶意代码分析难度,减少被发现的可能性
  • 加密技术:利用加密技术,提高恶意代码自身保护能力
    模糊变换技术:利用模糊变换技术,恶意代码可以躲避基于特征码的恶意代码检测系统,提高生存能力
  • 自动生产技术:利用自动生成技术,在已有的恶意代码的基础上自动生成特征码不断变化的新的恶意代码,从而躲避基于特征码的恶意代码检测。

3、攻击技术

  • 进程注入技术:恶意代码程序将自身嵌入到操作系统和网络系统的服务程序中,不但实现了自身的隐藏,而且还能随着服务的加载而启动。
  • 三线程技术:恶意代码进程同时开启三个线程,其中一个为主线程,负责远程控制的工作。另外两个辅助线程分别是监视和守护线程。一旦发现主线程被删除,则立即设法恢复。
  • 端口复用技术:重复利用系统或网络服务打开的端口(如80端口),可以欺骗防火墙,具有很强的欺骗性。
  • 超级管理技术:恶意代码采用超级管理技术对反恶意代码软件系统进行攻击,使其无法正常运行。
  • 端口反向连接技术:指使恶意代码的服务端(被控制端)主动连接客户端(控制端)的技术。
  • 缓冲区溢出技术:恶意代码利用系统和网络服务的安全漏洞植入并且执行攻击代码,造成缓冲区溢出,从而获得被攻击主机的控制权。

三、恶意代码传播方式及防范手段

1、传播方式

传播途径

  • 利用操作系统和应用软件的漏洞进行传播
  • 通过网站传播
    在网页上挂载恶意代码
    如:主机流览该网页时,恶意代码会自动下载到主机执行。
    将恶意代码与正常应用软件捆绑
    如:主机下载正常软件运行时,恶意代码也随之自动运行。
  • 利用移动媒介传播
    如:主机访问U盘和硬盘时,恶意代码可以自动执行。
  • 利用用户之间的信任关系传播
    如:冒充用户发送虚假链接、图片、邮件等。

总的来说,恶意代码的传播是因为用户的软件出现了漏洞、操作不慎或者是两者的结合造成。

(1)病毒。病毒具备有自我复制能力,一般嵌入主机的程序中。当被感染文件执行操作,如,用户打开一个可执行文件时,病毒就会自我繁殖。病毒一般都具有破坏性。
(2)木马。这种程序从表面上看没有危害,但实际上却隐含着恶意的意图和破坏的作用。一些木马程序会通过覆盖系统中已经存在的文件的方式存在于系统之中;另外有的还会以软件的形式出现,因为它一般是以一个正常的应用程序身份在系统中运行的,所以这种程序通常不容易被发现。
(3)蠕虫。蠕虫是一种可以自我复制的完全独立的程序,它的传播不需要借助被感染主机中的程序和用户的操作,而是通过系统存在的漏洞和设置的不安全性来进行入侵,如通过共享的设置来侵入。蠕虫可以自动创建与它的功能完全相同的副本,并能在无人干涉的情况下自动运行,大量地复制占用计算机的空间,使计算机的运行缓慢甚至瘫痪。

2、攻击机制

恶意代码的行为表现各异,破坏程度千差万别,但基本作用机制大体相同,其整个作用过程分为6个部分。
(1)侵入系统。侵入系统是而已代码实现其恶意目的的必要条件。恶意代码入侵的途径很多,包括前面传播方式的各种途径。如:从互联网下载的程序本身就可能含有而已代码;接收已感染恶意代码的电子邮件;从光盘或U盘往系统上安装软件;黑客或者攻击者故意将恶意代码植入系统等。
(2)维持或提升权限。恶意代码的传播与破坏必须盗用用户或者进程的合法权限才能完成。
(3)隐蔽策略。为了不让系统发现恶意代码已经侵入系统,恶意代码可能会改名、删除源文件或者修改系统的安全策略来隐藏自己。
(4)潜伏。恶意代码侵入系统后,等待一定的条件,并具有足够的权限时,就发作并进行破坏活动。
(5)破坏。恶意代码本质具有破坏性,其目的是造成信息丢失,泄密,破坏系统完整性等。
(6)重复(1)至(5)对新的目标实施攻击过程。
恶意代码的攻击模型

3、防范手段

通用恶意代码检测技术包括静态和动态检测技术:

  • 基于特征的扫描技术
    建立恶意代码的特征文件,在扫描时根据特征进行匹配查找

  • 校验和法
    对需要监控的文件生成校验,周期性的生成新校验和并与原始值比较

  • 沙箱技术
    根据程序需要的资源和拥有的权限建立运行沙箱,可以安全地检测和分析程序行为

  • 基于蜜罐的检测技术
    将主机伪装为运行着脆弱的服务或系统,同时安装强大的监测系统。

其中基于特征的扫描技术和校验和法是静态检测技术,沙箱技术和基于蜜罐的检测技术属于动态检测技术。

四、常见恶意代码

常见的恶意代码

参考文献:
《网络攻防技术与实战 深入理解信息安全防护体系》 郭帆
《恶意代码及其防御》知乎 Drifter
《恶意代码》MBA智库百科


博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

网络安全之暴露面、攻击面、脆弱性

发表于 2022-01-10 | 更新于: 2025-04-08 | 分类于 技术 , 网络安全 | | 阅读次数:
字数统计: 1k | 阅读时长 ≈ 3

暴露面
暴露在攻击者视线范围内,可以被利用进行入侵的系统、设备、信息等,都属于暴露面。虽然大多数企业都认识到暴露面的风险所在,并想方设法来减少暴露面;但不幸的是,并非所有暴露面都是显而易见的,大量的暴露面都潜藏在不容易被发现的暗处,很容易因为资产排查不彻底、人员疏漏等问题被忽略。互联网暴露面资产直接面向外部攻击者的威胁。相对于企业内部资产,所面临的安全风险更高。

攻击面
攻击面:是一个给定的计算机或网络系统,可以被黑客访问和利用的漏洞总和。
攻击面包含:
操作系统、中间件、应用程序、承载网络中存在的软件漏洞;
系统和软件中的错误配置与安全控制缺失;
违反安全制度和合规要求的网络配置;
过度宽松的访问控制规则;

减少攻击面的基本策略是减少运行中的软件总量,减少非信任用户可使用的入口点,以及消除用户很少使用的服务。改进信息安全的方法之一就是减少系统与软件的攻击表面。因为关闭不必要的功能,可以避免它们带来的安全风险。减少未授权操作者可调用的代码有助避免安全事故。虽然减少攻击表面有助于防止安全事故,但它不能减少一旦攻击者发现漏洞后可能造成的损害程度。

攻击面从外部攻击视角来审视企业网络资产可能存在的攻击面及脆弱性,如开放端口是否做映射、网络边界是否做隔离、人员行为是否被明确约束等。

脆弱性
脆弱性也可称为弱点或漏洞,是资产或资产组中存在的可能被威胁利用造成损害的薄弱环节。脆弱性一旦被威胁成功利用就可能对资产造成损害。脆弱性可能存在于物理环境、组织、过程、人员、管理、配置、硬件、软件和信息等各个方面。脆弱性是网络系统中可能被利用并造成危害的弱点。

三无七边系统
三无:指具有系统特征且存在”无人管理、无人使用、无人防护”情况的业务/网站/系统/平台。
七边:指测试系统、试验平台、退网未离网系统、工程已上线加载业务但未正式交维系统、与合作伙伴共同运营的业务或系统、责任交接不清的系统、处于衰退期的系统。
三无七边系统是往往是最容易被外部攻破和利用的,所以需要加以重视。但是”三无七边”往往是最不容易发现和忽视的。
“三无七边”系统网络安全管控工作应贯穿规划、设计、建设、入网运行、维护及下线退网整个生命周期。

暴露面不一定存在漏洞也不一定是攻击面,但是因为暴露在攻击者视线范围内,直面外部攻击者的威胁,安全风险高。
攻击面我的理解是既可以被黑客访问又存在漏洞,也就是既是暴露面又有脆弱性,安全风险非常高。
攻击面是从外部攻击的视角来审视可能存在的风险,暴露面和脆弱性从内部管理的视角来审视安全风险。
三无七边系统往往是安全管理人员所忽视的有可能存在暴露面和攻击面而又没有在安全管控范围内的系统,安全风险非常非常高。


作者博客:http://xiejava.ishareread.com


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

不想学鼓的产品经理不是一个好的程序员

发表于 2021-12-29 | 更新于: 2025-04-08 | 分类于 人生 | | 阅读次数:
字数统计: 697 | 阅读时长 ≈ 2

架子鼓

架子鼓

一直以来都想学一门乐器。苦于没有任何才艺,不管是学校搞活动还是公司的团拜活动都是躲得远远的。从小就很羡慕那种多才多艺的人,不管什么时候都能成为众人的焦点,在要表演的时候可以自信的拿得出手表现一番。也非常羡慕那种自娱自乐的享受自我放松的自由演奏,感觉会乐器的人总是那么的快乐和陶醉。

公司搬到岳麓山大学科技城就在中南大学后湖国际艺术园。一天晚上和同事散步经过一家现代音乐体验店,里面传来乐队演奏的声音,于是驻足前往。里面一群快乐的人,正在激情洋溢的排练着享受着。我们都被触动了,这种自由、快乐、充满激情的感觉真好!想着一天到晚围绕着产品、项目、代码、缺陷,被工作和生活的压力摧残着的我们什么时候才会有这样的状态啊?所以合计了一下,我们也来报个班来学乐器。我一直想学架子鼓,所以决定报个学架子鼓的班。

试听课,老师是一位胖胖的90后小女孩,问了我一个灵魂拷问的问题。你这年纪不小了为什么想起要来学架子鼓?我想了半天,说我就是喜欢敲鼓啊,一直一来就喜欢节奏感比较强的声音,听音乐也是喜欢听节奏感强的歌曲,听到重低音的鼓声敲在心里“咚”、“咚”、“咚”的感觉很踏实。而且敲鼓沉浸在音乐里敲起来帅气。不管怎么样,虽然不会,但是从心里还是喜欢。

喜欢是喜欢,但是没有目标的学习始终都是在耍流氓,浪费自己的时间、精力还学不好。既然是喜欢,既然开始学了,就一定要学好。我们现在是报的一个课程12节课的班,我的目标是通过这一个课程的学习,了解架子鼓的基本演奏技巧,学会一首歌曲的演奏。就《大风吹》吧,谁叫这歌这段时间这么火呢。计划是每周二、四上课,每天拿出1个小时用来练习。学鼓,虽然我不是天赋最好的,但我争取做那个最认真的!

今天根据老师的建议在网上买了练习用的哑鼓垫、军鼓架、鼓棒、节拍器。后面动次打次练起来!

以后我的标签又多了一个–鼓手!



“fullbug”微信公众号

关注:微信公众号,一起学习成长!

穷忙与假努力

发表于 2021-12-28 | 更新于: 2025-04-08 | 分类于 人生 | | 阅读次数:
字数统计: 1.4k | 阅读时长 ≈ 4

穷忙与假努力

穷忙与假努力

时间过得真快,只有几天2021年即将过去。每次到了年底回想起来总是感觉时间过得真快,忙忙碌碌又过了一年,可自己各方面取得的成绩乏善可陈。自己并不是很懒惰的人,看上去每天都很忙,却没有忙出效果,反而是随着年龄的增大越来越焦虑。越焦虑就暗自下决心以后要更加努力,当努力没有达到效果时就更加的焦虑。陷入了越努力->越失望->越焦虑的怪圈。

没有目标、没有效果的忙就是穷忙,看上去努力却实际没有效果的努力是假努力,穷忙和假努力往往是一同出现的,假努力造成了穷忙,穷忙成就了假努力。相对于不努力,有时候“假努力”会更加可怕!因为它像安慰剂一样,让你感觉是在努力而不自知,会让你陷入深深的自我怀疑,对自己失望,最后越来越糟,失去对学习、工作、生活的兴趣。

到底什么样的表现是“假努力”呢?有老师针对孩子们在学习上的表现列举了一些“假努力”表现,给了我很大的启发。

“假努力”表现一:上课只顾抄笔记,老师讲的都不听。
有很多同学在上课的时候表现得特别忙,看上去特别努力的在学习,老师黑板上写的,还是口头上说的,他们都会事无巨细地写下来。然而,对于老师们讲的是什么?本节课的重难点又是什么?他们全然无所谓,只顾着把这堂课发生的所有一切都记录下来。这样的“假努力”注定会让课堂的效率低下,让自己的努力完全沦为无用的“假努力”。

“假努力”表现二:花很多时间做笔记,课后却从来不去理解。
有第一种“假努力”的同学,往往都存在着“假努力”的第二种表现,那就是笔记写得非常非常多,但是至于笔者写的内容和知识点,他们都从来不看,更不会花时间去理解和搞懂笔记上的内容。这样花大力气写下的笔记,当然最终沦为无用功。

“假努力”表现三:只顾刷题,从来都不花时间总结。
还有一部分“假努力”的同学,每天花大量的时间刷题,而且他们往往还有一个显著的特征,那就是只管做题多少,从来不过问题目对错!那些错题,反复出现问题的题目,他们从来都是不管不顾,只觉得刷了足够的题目,自己的成绩自然而然会上升!然而,殊不知他们把大量的时间花在了已经会的题目上,那些不会、易错的题目还是永远会错。

“假努力”表现四:每天熬夜学习,白天学习效率低下。
不知道各位老师和同学有没有发现,几乎每一个中学班级里,总会出现这么一两个“夜晚学习狂魔”,他么总喜欢晚上搞学习,并且熬非常的时间,导致第二天整个人的精神状态都不好,白天的学习效率极其低下!最后陷入一个“白天该学的时候状态差,晚上不该学的时候拼命学”的死循环当中。

“假努力”表现五:没有目标和计划的去学习。
这种“假努力”的表现有一个典型的例子,比如某个同学们英语很差,想通过自己的努力学好英语,然后就从英语单词开始入手,每天背课本上的单词,而且无论什么时候都是从单词表的第一个单词去背起!这样无计划、无目标的努力,只会耗费巨大的时间和精力在重复学习之上!进而导致学习成绩的速度异常的缓慢!

从这些表现上来看,其实我们成年人在平时学习、工作中同样存在这些类似的问题。个人认为造成穷忙和假努力最大的问题是没有目标和计划。东一榔头、西一棒子,不知道自己到底要学什么,要学到一个什么样的程度。就像小时候课本里的小猴子去掰玉米,看什么捡什么,最后捡了芝麻丢了西瓜。另外一个就是要有系统化、体系化的思维去学习。只有系统化、体系化的去学习某个东西,建立该领域的知识体系结构体系才能在有体系结构的基础上进行积累,才能学得好,学得牢。现在公众号、抖音、知乎上碎片化的知识很多,哪怕你是天天上知乎去关注学习这些碎片化的知识而没有建立一个知识体系去有意识的去理解吸收的话,那就类似于花了很多时间去做笔记,去关注去了解,课后从来不去理解。给人感觉是看上去在很努力的学习,其实啥也没有学到。


博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

新场地,新征程!

发表于 2021-12-10 | 更新于: 2025-04-08 | 分类于 人生 | | 阅读次数:
字数统计: 144 | 阅读时长 ≈ 1

服务数字经济,护航美好生活!

2021年12月09日通服网安研发团队强势入驻岳麓上大学科技城国家网络安全产业园。

新场地,新征程,数网络安全研发,还看通服网安!

通服网安揭牌

通服网安

通服网安研发团队

通服网安研发团队

通服网安研发大楼

通服网安研发大楼

通服网安研发大楼外景

通服网安研发大楼外景

通服网安前台

通服网安前台

展厅入口

通服网安展厅入口

通服网安展厅

通服网安展厅

通服网安研发楼展厅安全运营中心展示

通服网安研发楼展厅安全运营中心展示

没有网络安全就没有国家安全

没有网络安全就没有国家安全

机器学习实现恶意URL检测实战一

发表于 2021-12-09 | 更新于: 2025-04-08 | 分类于 技术 , 开发 , 网络安全 | | 阅读次数:
字数统计: 1.1k | 阅读时长 ≈ 4

恶意URL检测的方法很多,这里介绍通过机器学习分析URL文本分词词频来检测恶意URL。训练的数据集为开源数据集,通过机器学习训练检测模型,然后做了部分工程化的应用,将模型持久化,在应用的时候加载进来直接应用,不用重新进行训练。通过接口调用实现恶意URL检测预测判断。

恶意URL检测,对应与机器学习是个分类问题,这里分别用逻辑回归和SVM支持向量机分类模型进行模型实现。

具体实现过程包括数据载入–>数据处理(分词、向量化处理)–>模型训练–>模型保存–>模型应用

项目组织结构如下:
项目组织结构

一、数据载入

从数据集中载入数据,读取数据,将URL和标签进行识别和区分。

1
2
3
4
5
6
7
8
9
10
#从文件中获取数据集
def getDataFromFile(filename='data/data.csv'):
input_url = filename
data_csv = pd.read_csv(input_url, ',', error_bad_lines=False)
data_df = pd.DataFrame(data_csv)
url_df = np.array(data_df)
random.shuffle(url_df)
y = [d[1] for d in url_df]
inputurls = [d[0] for d in url_df]
return inputurls,y

二、数据处理(分词、向量化处理)

数据处理实现对URL的分词及向量化处理
分词:分析URL根据,.-进行分词,由于com、cn等常用域名不是关键影响因素,所以分词的时候去掉了

分词

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#分词
def getTokens(input):
web_url = input.lower()
urltoken = []
dot_slash = []
slash = str(web_url).split('/')
for i in slash:
r1 = str(i).split('-')
token_slash = []
for j in range(0, len(r1)):
r2 = str(r1[j]).split('.')
token_slash = token_slash + r2
dot_slash = dot_slash + r1 + token_slash
urltoken = list(set(dot_slash))
if 'com' in urltoken:
urltoken.remove('com')
if 'cn' in urltoken:
urltoken.remove('cn')
return urltoken

向量化处理

将分词以后的结果进行词频的向量化处理,形成可以用于模型训练的稀疏矩阵向量

1
2
3
all_urls,y=getDataFromFile(datapath)
url_vectorizer = TfidfVectorizer(tokenizer=getTokens)
x = url_vectorizer.fit_transform(all_urls)

三、模型训练

将经过处理后的训练数据用模型进行训练,将数据集分为两部分一部分用于训练,一部分用于测试评估。

1
2
3
4
5
6
7
8
9
10
11
#训练,通过逻辑回归模型训练
def trainLR(datapath):
all_urls,y=getDataFromFile(datapath)
url_vectorizer = TfidfVectorizer(tokenizer=getTokens)
x = url_vectorizer.fit_transform(all_urls)
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
l_regress = LogisticRegression() # Logistic regression
l_regress.fit(x_train, y_train)
l_score = l_regress.score(x_test, y_test)
print("score: {0:.2f} %".format(100 * l_score))
return l_regress,url_vectorizer

用逻辑回归模型训练的结果是 score: 98.50 %

1
2
3
4
5
6
7
8
9
10
11
#训练,通过SVM支持向量机模型训练
def trainSVM(datapath):
all_urls, y = getDataFromFile(datapath)
url_vectorizer = TfidfVectorizer(tokenizer=getTokens)
x = url_vectorizer.fit_transform(all_urls)
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
svmModel=svm.LinearSVC()
svmModel.fit(x_train, y_train)
svm_score=svmModel.score(x_test, y_test)
print("score: {0:.2f} %".format(100 * svm_score))
return svmModel,url_vectorizer

用SVM模型训练的结果是 score: 99.64 %

可以看出SVM模型训练的结果比逻辑回归模型训练的效果要稍好。

四、保存模型

将训练好的模型进行持久化保存,通过pickle.dump()的方式把训练好的模型参数及特征保存至模型文件,以便于应用的时候不要再进行训练,直接应用训练好的模型。

1
2
3
4
5
6
7
8
9
10
11
12
#保存模型及特征
def saveModel(model,vector):
#保存模型
file1 = modelfile_path
with open(file1, 'wb') as f:
pickle.dump(model, f)
f.close()
#保存特征
file2 = vectorfile_path
with open(file2, 'wb') as f2:
pickle.dump(vector, f2)
f2.close()

通过main方法执行训练模型及保存模型

1
2
3
4
if __name__ == '__main__':
#model,vector=trainLR('data/data.csv')
model, vector = trainSVM('data/data.csv')
saveModel(model,vector)

四、模型应用

通过pickle.load载入已经训练好的模型和特征,并用Flask暴露一个接口调用模型的预测方法进行预测。

载入已经训练好的模型

1
2
3
4
5
6
7
8
9
10
11
12
#载入已经训练好的模型
def loadModel():
file1 = modelfile_path
with open(file1, 'rb') as f1:
model = pickle.load(f1)
f1.close()

file2 = vectorfile_path
with open(file2, 'rb') as f2:
vector = pickle.load(f2)
f2.close()
return model,vector

通过接口进行调用

1
2
3
4
5
6
7
8
9
10
#通过接口进行调用
@app.route('/<path:path>')
def show_predict(path):
X_predict = []
X_predict.append(path)
model, vector = loadModel()
x = vector.transform(X_predict)
y_predict = model.predict(x)
print(y_predict[0])
return "url predict: "+str(y_predict[0])

五、应用效果

将需要检测的URL,输入到http://127.0.0.1:5000/后面,就可以根据输入的URL进行检测给出模型预测的结果。
http://127.0.0.1:5000/sohu.com/a/338823532_354899
检测效果1
http://127.0.0.1:5000/sohu.com/a/%3Cscript%3E/test
检测效果2

完整代码及数据集见:https://github.com/xiejava1018/urldetection.git


博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

<1…151617…20>
XieJava

XieJava

200 日志
11 分类
25 标签
RSS
GitHub
友情链接
  • 爱分享读书
  • CSDN
  • 豆瓣
© 2025 XieJava | Site words total count: 415.3k

主题 — NexT.Muse
0%