【数据分析“三剑客”】—— Pandas

Pandas

  • Pandas 是基于NumPy的一种工具,该工具是为解决数据分析任务而创建的, Pandas提供了大量能使我们快速便捷地处理数据的函数和方法。
  • Pandas与出色的 Jupyter工具包和其他库相结合,Python中用于进行数据分析的环境在性能、生产率和协作能力方面都是卓越的。
  • Pandas的主要数据结构是 **Series(**一维数据)与 **DataFrame **(二维数据),Pandas的Series和DataFrame在数据分析领域引入了更多高级功能和更丰富的数据结构,特别是需要处理结构化数据、缺失值、时间序列以及进行复杂统计分析时。

导包

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

Series

Series是一种类似于一维数组的对象,由下面两个部分组成:

  • values:一组数据(ndarray类型)
  • index:相关的数据索引标签

Series可以看作是ndarray数组的升级版,因为它不仅存储数据,还存储了数据的索引,这样就可以通过标签来访问数据,而不仅仅是基于位置的访问。

Series的创建

两种创建方式:

由列表或NumPy数组创建

list1 = [11, 22, 33, 44]
n = np.array(list1)
type(n)  # numpy.ndarrays = Series(n)
display(type(s))  # pandas.core.series.Series

Series属性: index和values

# values属性
s.values  # array([11, 22, 33, 44])s.index
# RangeIndex(start=0, stop=4, step=1)
list(s.index)# 修改索引
s.index = list("abcd")
s.index = ["鲁班", "李白", "诸葛亮", "张飞"]
display(s)# 通过索引取值
s.鲁班, s['鲁班']# 通过索引修改值
s['鲁班'] = 100

通过字典创建

d = {'a': 11,'b': 22,'c': 33,'d': 44
}
s = Series(d)
s.index = list("ABCD")
display(s)d = {'a': np.random.randint(0, 10, size=(2,3)),'b': np.random.randint(0, 10, size=(2,3)),'c': np.random.randint(0, 10, size=(2,3)),'d': np.random.randint(0, 10, size=(2,3))
}
s = Series(d)
display(s)# 创建时同时设置索引
s = Series([1,2,3], index=["张三", '李四', '王五'])
display(s)

Series的索引

可以使用中括号取单个索引(此时返回的是元素类型),或者中括号里一个列表取多个索引(此时返回的仍然是一个Series类型)。分为显示索引和隐式索引:

(1) 显式索引:
  • 使用index中的元素作为索引值
  • 使用.loc[]

注意,此时是闭区间

s = Series({'语文': 150, "数学": 100, "英语": 120, "Python": 99})# 显式索引:使用索引名字
s['语文']  # int类型
s[['语文', "Python", "数学"]]  # Series类型
s[['语文']]  # Series类型# .loc[ ]
s.loc['语文']
s.loc[['语文', "Python", "数学"]] 
s.loc[['语文']]
(2) 隐式索引:
  • 使用整数作为索引值
  • 使用.iloc[](推荐)integer location 整数位置

注意,此时是半开区间

s = Series({'语文': 150, "数学": 100, "英语": 120, "Python": 99})# 隐式索引: 使用数字下标
s[0]
s[[0, 2, 1]]
s[[0]]# iloc[ ]
s.iloc[0]
s.iloc[[0, 2, 1]]
s.iloc[[0]]

Series的切片

  • Series一维数组切片
s = Series({'语文': 150, "数学": 100, "英语": 120, "Python": 99, "Numpy": 66, "Pandas": 199})# Series是一维数组# 显式切片: 闭区间
s["数学": "Python"]
s.loc["数学": "Python"]# 隐式切片 : 左闭右开
s[1: 4]
s.iloc[1: 4]

Series的属性和方法

  • shape 形状
  • size 大小
  • index 索引
  • values 值
  • dtype 元素类型
  • name 名字
s.shape  # 形状
s.size  # 元素个数
s.index  # 索引
s.values  # 值
s.dtype  # 元素类型s = Series([11, 22, 33], name="年龄")
s.name  # Series名字

查看首尾数据

  • head() 查看前几条数据,默认5条
  • tail() 查看后几条数据,默认5
# 查看前几条数据,默认5条
head() 
s.head()  
s.head(2)# 查看后几条数据,默认5
tail() 
s.tail()
s.tail(2)

检测缺失数据

  • pd.isnull()
  • pd.notnull()
  • isnull()
  • notnull()
# s.isnul()
pd.isnull(s)# s.notnull()
pd.notnull(s)# 可以通过True,Flase过滤数据# 保留不为空的数据
s[ pd.notnull(s) ]

Series的运算

(1) 适用于NumPy的数乘运算也适用于Series
s = Series(np.random.randint(10, 100, size=10))s + 100
s - 100
s * 100
s / 100
s // 10
s ** 2
(2) Series之间的运算
  • 在运算中自动对齐索引的数据
  • 如果索引不对应,则补NaN
  • Series没有广播机制
s1 = Series(np.random.randint(10, 100, size=3))
s2 = Series(np.random.randint(10, 100, size=4))
display(s1 + s2)# Numpy中有广播机制
n1 = np.array(np.random.randint(1, 10, size=(1, 3)))
n2 = np.array(np.random.randint(1, 10, size=(3, 1)))
display(n1 + n2)
  • 注意:要想保留所有的index,类似于sql的全连接,保存两个运算对象的所有index,则需要使用.add()函数,使用NaN补齐运算结果
s1.add(s2, fill_value=100)

DataFrame

DataFrame是一个二维表格型的数据结构,可以看做是由Series组成的字典。DataFrame由按一定顺序排列的多列数据组成。设计初衷是将Series的使用场景从一维拓展到多维。DataFrame既有行索引,也有列索引。

  • 行索引:index
  • 列索引:columns
  • 值:values

DataFrame的创建

最常用的方法是传递一个字典来创建。DataFrame以字典的键作为每一列的索引名称,以字典的值(一个数组)作为每一列的内容。此外,DataFrame会自动加上每一行的索引,行索引为从0开始的自然数。

同Series一样,若传入的列与字典的键不匹配,则相应的值为NaN

d = {'name' : ["鲁班", '陈咬金', "猪八戒"],'age' : [7, 9, 8],'sex': ['男', '女', '男']
}
df = DataFrame(d)

在创建时,指定数据、行索引和列索引

df = DataFrame(data=np.random.randint(0, 100, size=(4, 6)),index=['小明', "小红", '小绿', '小黄'],columns=['语文', '数学', '英语', 'Python', 'Numpy', 'Pandas']
)
df

DataFrame属性和方法

  • values 值
  • columns 列索引
  • index 行索引
  • shape 形状
  • head() 查看前几行数据
  • tail() 查看后几行数据
# 创建DataFrame
df = DataFrame(d, index=["第一行", "第二行", "第三行"])df.values  # 值,二维ndarray数组
df.columns   # 列索引
df.index  # 行索引
df.shape  # 形状# 查看首尾数据
df.head(2)
df.tail(2)

DataFrame的索引

对列进行索引

  • 通过类似字典的方式
  • 通过属性的方式

可以将DataFrame的列获取为一个Series。返回的Series拥有原DataFrame相同的索引,且name属性也已经设置好了,就是相应的列名。

df = DataFrame(data=np.random.randint(0, 100, size=(4, 6)),index=['小明', "小红", '小绿', '小黄'],columns=['语文', '数学', '英语', 'Python', 'Numpy', 'Pandas']
)df.语文
df['语文']  # Seriesdf[['语文', 'Python']]  # DataFrame
df[['语文']]

对行进行索引

  • 使用.loc[ ]加index来进行行索引
  • 使用.iloc[ ]加整数来进行行索引

同样返回一个Series,index为原来的columns。

df = DataFrame(data=np.random.randint(0, 100, size=(4, 6)),index=['小明', "小红", '小绿', '小黄'],columns=['语文', '数学', '英语', 'Python', 'Numpy', 'Pandas']
)# DataFrame默认取列索引
df.loc['小明']  # Series
df.iloc[0]df.loc[['小明', '小绿']]  # DataFrame
df.loc[['小明']] 
df.iloc[[0, 2]]  # DataFrame
df.iloc[[0]]

对元素索引的方法

df = DataFrame(data=np.random.randint(0, 100, size=(4, 6)),index=['小明', "小红", '小绿', '小黄'],columns=['语文', '数学', '英语', 'Python', 'Numpy', 'Pandas']
)# 先取列,再取行
df['语文'][1]
df['语文']['小明']# 先取行,再取列
df.iloc[1]['语文']  # 列索引的符号不可以用整数代替
# df.loc['小明', '语文']  

DataFrame的切片

【注意】 直接用中括号时:

  • 索引表示的是列索引
  • 切片表示的是行切片
df = DataFrame(data=np.random.randint(0, 100, size=(4, 6)),index=['小明', "小红", '小绿', '小黄'],columns=['语文', '数学', '英语', 'Python', 'Numpy', 'Pandas']
)# 索引: 优先使用列索引, 先取行就需要写loc或iloc
# 切片: 优先按行切片, 和Numpy操作类似# 行: 行名, 行数字索引
# 列: 列名# 行切片
df[1 : 3]  # 左闭右开
df['小明' : "小绿"]  # 闭区间df.iloc[1 : 3]
df.loc['小明' : "小绿"]# 列切片: 需要使用loc或iloc
df.iloc[:, 1:3]
df.loc[:, "数学": "Python"]df.loc["小明":"小绿", "数学":"Python"]
df.iloc[:3, 1:4]

DataFrame的运算

DataFrame之间的运算
  • 在运算中自动对齐索引的数据
  • 如果索引不对应,则补NaN
  • DataFrame没有广播机制
# 创建DataFrame df1 不同人员的各科目成绩,月考一
df1 = DataFrame(data={'Python': [100, 90, 80], 'Java': [80, 70, 60], 'PHP': [60, 50, 40]},index=['张飞', "吕布", '关羽']
)# 创建DataFrame df2 不同人员的各科目成绩,月考二
df2 = DataFrame(data={'Python': [100, 90, 80, 70], 'Java': [80, 70, 60, 50], 'PHP': [60, 50, 40, 30], 'Go': [40, 30, 20, 10]},index=['张飞', "吕布", '关羽', "刘备"]
)# DataFrame和数的运算
display(df1 + 100)# DataFrame之间的运算
display(df1 + df2)# 自动填充, 再相加
df1.add(df2, fill_value=1000)
Series与DataFrame之间的运算
  • 使用Python操作符:以行为单位操作(参数必须是行),对所有行都有效。(类似于numpy中二维数组与一维数组的运算,但可能出现NaN)

  • 使用pandas操作函数:

    axis=0:以列为单位操作(参数必须是列),对所有列都有效。
    axis=1:以行为单位操作(参数必须是行),对所有行都有效。

# 创建DataFrame df1 不同人员的各科目成绩,月考一
df1 = DataFrame(data={'Python': [100, 90, 80], 'Java': [80, 70, 60], 'PHP': [60, 50, 40]},index=['张飞', "吕布", '关羽']
)s = Series([100, 10, 1], index=df1.columns)# 直接相加
df1 + s# 使用add函数
df1.add(s)
df1.add(s, axis='columns')  # 列
df1.add(s, axis=1)  # 第二个维度s = Series([100, 10, 1], index=df1.index)
df1.add(s, axis='index')  # 行
df1.add(s, axis=0)  # 行

Pandas层次化索引

创建多层行索引

隐式构造

  • 最常见的方法是给DataFrame构造函数的index参数传递两个或更多的数组
data = np.random.randint(0, 100, size=(6, 6))index = [['1班', '1班', '1班', '2班', '2班', '2班'],['张三', '李四', '王五', '赵六', '田七', '孙八']
]columns = [['期中', '期中', '期中', '期末', '期末', '期末'],['语文', '数学', '英语', '语文', '数学', '英语']
]df = pd.DataFrame(data=data, index=index, columns=columns)
df
  • Series也可以创建多层索引
data = np.random.randint(0, 100, size=6)index = [['1班', '1班', '1班', '2班', '2班', '2班'],['张三', '李四', '王五', '赵六', '田七', '孙八']
]s  = pd.Series(data=data, index=index)
s

显示构造pd.MultiIndex

  • 使用数组
data = np.random.randint(0, 100, size=(6, 6))index = pd.MultiIndex.from_arrays( [['1班', '1班', '1班', '2班', '2班', '2班'],['张三', '李四', '王五', '赵六', '田七', '孙八']
] )columns = [['期中', '期中', '期中', '期末', '期末', '期末'],['语文', '数学', '英语', '语文', '数学', '英语']
]df = pd.DataFrame(data=data, index=index, columns=columns)
df
  • 使用tuple
data = np.random.randint(0, 100, size=(6, 6))index = pd.MultiIndex.from_tuples( (('1班', '张三'), ('1班', '李四'), ('1班', '王五'), ('2班', '赵六'), ('2班', '田七'), ('2班', '孙八'), )
)columns = [['期中', '期中', '期中', '期末', '期末', '期末'],['语文', '数学', '英语', '语文', '数学', '英语']
]df = pd.DataFrame(data=data, index=index, columns=columns)
df
  • 使用product
data = np.random.randint(0, 100, size=(6, 6))# 笛卡尔积:{a, b} {c, d} => {a,c}, {a,d}, {b,c}, {b,d}
index = pd.MultiIndex.from_product( [['1班',  '2班'],['张三', '李四', '王五']]
)columns = [['期中', '期中', '期中', '期末', '期末', '期末'],['语文', '数学', '英语', '语文', '数学', '英语']
]df = pd.DataFrame(data=data, index=index, columns=columns)
df

创建多层列索引(同行索引)

除了行索引index,列索引columns也能用同样的方法创建多层索引

多层索引对象的索引与切片操作

Series的操作【重要】

对于Series来说,直接中括号[]与使用.loc()完全一样

# (1) 索引
data = np.random.randint(0, 100, size=6)index = [['1班', '1班', '1班', '2班', '2班', '2班'],['张三', '李四', '王五', '赵六', '田七', '孙八']
]s  = pd.Series(data=data, index=index)
s# 显式索引
s['1班']
s.loc['1班']s.loc[['1班']]
s.loc[['1班', '2班']]s['1班']['张三']
s.loc['1班']['张三']
s.loc['1班','张三']
s['1班', '张三']#隐式索引
s[1]
s.iloc[1]
s.iloc[[3, 2]]# (2) 切片
# 显式切片
s['1班': '1班']
s.loc['1班': '2班']
# s.loc['李四': '田七']  # 没有结果
# s.loc[('1班', '李四'): ('2班', '田七')]   # 报错, 显式切片只对最外层索引有效# 建议使用隐式切片
s[1: 4]
s.iloc[1: 5]

DataFrame的操作

  • 可以直接使用列名称来进行列索引
  • 使用行索引需要用iloc(),loc()等函数
  • 无法直接对二级索引进行索引
data = np.random.randint(0, 100, size=(6, 6))index = pd.MultiIndex.from_product( [['1班',  '2班'],['张三', '李四', '王五']]
)
columns = [['期中', '期中', '期中', '期末', '期末', '期末'],['语文', '数学', '英语', '语文', '数学', '英语']
]
df = pd.DataFrame(data=data, index=index, columns=columns)# 获取元素
df['期中']['数学'][1]df.iloc[1, 3]  # 第1行,第3列(索引)  42
df.loc[('1班', '李四'), ('期末', '语文')]  # 42# 列索引
df['期中']
df['期中']['数学']
df['期中', '数学']
# df[('期中', '数学')]
# df.期中.数学df.iloc[:, 2]
df.iloc[:, [1,2,3]]# 行索引
df.loc['1班']
df.loc['1班'].loc['张三']
df.loc['1班', '张三']
df.loc[('1班', '张三')]df.iloc[1]
df.iloc[[1]]
df.iloc[[1,2,3]]# 切片
# 行切片
df.iloc[1:5]
df.loc['1班' : '2班']
df.loc[('1班', '李四') : ('2班', '李四')]# 列切片
df.iloc[:, 1: 5]
df.loc[:, '期中': '期末']
# df.loc[:, ('期中', '数学'): ('期末', '数学')]  # 报错

索引的堆叠

使用stack()的时候,level等于哪一个,哪一个就消失,出现在行里。

data = np.random.randint(0, 100, size=(6, 6))
index = pd.MultiIndex.from_product( [['1班',  '2班'],['张三', '李四', '王五']]
)
columns = [['期中', '期中', '期中', '期末', '期末', '期末'],['语文', '数学', '英语', '语文', '数学', '英语']
]
df = pd.DataFrame(data=data, index=index, columns=columns)# stack: 列索引变成行索引
df.stack()  # 默认level=-1 (倒数第一层),将最里层的列索引 变成行索引
df.stack(level=1) df.stack(level=0)  # 将最外层的列索引 变成行索引

使用unstack()的时候,level等于哪一个,哪一个就消失,出现在列里。

# unstack : 将行索引 变成 列索引
df.unstack()
df.unstack(level=1)df.unstack(level=0)

使用fill_value填充

data = np.random.randint(0, 100, size=(6, 6))
index = pd.MultiIndex.from_tuples( (('1班', '张三'), ('1班', '李四'), ('1班', '王五'), ('2班', '赵六'), ('2班', '田七'), ('2班', '孙八'), )
)
columns = [['期中', '期中', '期中', '期末', '期末', '期末'],['语文', '数学', '英语', '语文', '数学', '英语']
]
df2 = pd.DataFrame(data=data, index=index, columns=columns)df2.unstack()
df2.unstack(fill_value=0)

聚合操作

  • 需要指定axis
  • 和unstack()相反,聚合的时候,axis等于哪一个,哪一个就保留。
data = np.random.randint(0, 100, size=(6, 6))
index = pd.MultiIndex.from_tuples( (('1班', '张三'), ('1班', '李四'), ('1班', '王五'), ('2班', '赵六'), ('2班', '田七'), ('2班', '孙八'), )
)
columns = [['期中', '期中', '期中', '期末', '期末', '期末'],['语文', '数学', '英语', '语文', '数学', '英语']
]
df2 = pd.DataFrame(data=data, index=index, columns=columns)# DataFrame聚合操作:求和,平均值,最大值,最小值....
df3 = df.loc['1班', '期中']# axis : 0表式行index, 1表式列columns
df3.sum()
df3.sum(axis=0)  # 对同一列的多行进行求和
df3.sum(axis=1)  # 对同一行的多列进行求和# 多层索引聚合操作
df.sum()  #  默认是对同一列的多行求和
df.sum(axis=1)   # 对同一行的多列求和
df.sum(axis=0, level=0)   # 表式 行 索引中的最外层
df.sum(axis=1, level=0)   # 表式 列 索引中的最外层
df.sum(axis=0, level=1)   # 表式 行 索引中的最里层
df.sum(axis=1, level=1)   # 表式 列 索引中的最里层

Pandas数据合并

  • pd.concat
  • pd.append
  • pd.merge

为了方便,我们首先定义一个生成DataFrame的函数:

def make_df(indexs, columns):    data = [[str(j)+str(i) for j in columns] for i in indexs]df = pd.DataFrame(data=data, index=indexs, columns=columns)return df# 调用
# make_df([1, 2, 3, 4], list('ABCD'))

使用pd.concat()级联

Pandas使用pd.concat函数,与NumPy中的concatenate函数类似,只是多了一些参数:

简单级联

df1 = make_df([1, 2], ['A', 'B'])
df2 = make_df([3, 4], ['A', 'B'])
display(df1, df2)# 上下合并,垂直合并
pd.concat([df1, df2])  # 左右合并,水平合并
pd.concat([df1, df2], axis=1) # 忽略行索引,重置行索引
pd.concat([df1, df2], ignore_index=True)  # 使用多层索引 keys
pd.concat([df1, df2], keys=['x', 'y'])    
# pd.concat([df1, df2], keys=['x', 'y'], axis=1)    

不匹配级联

不匹配指的是级联的维度的索引不一致。例如纵向级联时列索引不一致,横向级联时行索引不一致

df3 = make_df([1, 2, 3, 4], ['A', 'B', 'C', 'D'])
df4 = make_df([2, 3, 4, 5], ['B', 'C', 'D', 'E'])
display(df3, df4)# 对应索引没有值的会自动用NaN填充
pd.concat([df3, df4])# 外连接:补NaN(默认模式), 默认值outer,类似并集, 所有数据都会显示
pd.concat([df3, df4])
pd.concat([df3, df4], join='outer')# 内连接:只连接匹配的项, 交集, 只显示共同的列或行
pd.concat([df3, df4], join='inner')

使用append()函数添加

由于在后面级联的使用非常普遍,因此有一个函数append专门用于在后面添加

df3 = make_df([1, 2, 3, 4], ['A', 'B', 'C', 'D'])
df4 = make_df([2, 3, 4, 5], ['B', 'C', 'D', 'E'])
display(df3, df4)df3.append(df4, sort=True)

使用merge()合并

  • 类似MySQL中表和表之间的合并
  • merge与concat的区别在于,merge需要依据某一共同的行或列来进行合并
  • 使用pd.merge()合并时,会自动根据两者相同column名称的那一列,作为key来进行合并。
  • 每一列元素的顺序不要求一致

一对一合并

df1 = pd.DataFrame({'name': ['张三', '李四', '王五'],'id' : [1, 2, 3],'age': [22, 33, 44]
})
df2 = pd.DataFrame({'id' : [2, 3, 4],'sex': ['男', '女', '女'],'job': ['saler', 'CTO', 'Programer']
})
display(df1, df2)# 合并
# pd.merge(df1, df2)
df1.merge(df2)

多对一合并

df1 = pd.DataFrame({'name': ['张三', '李四', '王五'],'id' : [1, 2, 2],'age': [22, 33, 44]
})
df2 = pd.DataFrame({'id' : [2, 3, 4],'sex': ['男', '女', '女'],'job': ['saler', 'CTO', 'Programer']
})
display(df1, df2)# 合并
df1.merge(df2)

多对多合并

df1 = pd.DataFrame({'name': ['张三', '李四', '王五'],'id' : [1, 2, 2],'age': [22, 33, 44]
})
df2 = pd.DataFrame({'id' : [2, 2, 4],'sex': ['男', '女', '女'],'job': ['saler', 'CTO', 'Programer']
})
display(df1, df2)# 合并
df1.merge(df2)

key的规范化

  • 使用on=显式指定哪一列为key,当有多个key相同时使用
df1 = pd.DataFrame({'name': ['张三', '李四', '王五'],'id' : [1, 2, 3],'age': [22, 33, 44]
})
df2 = pd.DataFrame({'id' : [2, 3, 4],'name': ['李四', '王五', '赵六'],'job': ['saler', 'CTO', 'Programer']
})
display(df1, df2)# 如果有多列名称相同, 则需要指定一列作为连接的字段
df1.merge(df2, on='id')
df1.merge(df2, on='name')
  • 使用left_on和right_on指定左右两边的列作为key,当左右两边的key都不想等时使用
# 如果没有相同的列名,则需要使用left_on和right_on来分别指定2个表的列作为连接的字段
df1.merge(df2, left_on='id', right_on='id2')
  • 当左边的列和右边的index相同的时候,使用right_index=True
df1.merge(df2, left_index=True, right_on='id2')

内合并与外合并

  • 内合并:只保留两者都有的key(默认模式)
df1 = pd.DataFrame({'name': ['张三', '李四', '王五'],'id' : [1, 2, 3],'age': [22, 33, 44]
})
df2 = pd.DataFrame({'id' : [2, 3, 4],'sex': ['男', '女', '女'],'job': ['saler', 'CTO', 'Programer']
})
display(df1, df2)# 内连接: inner join
df1.merge(df2)
df1.merge(df2, how='inner')
  • 外合并 how=‘outer’:补NaN
# 外连接: 
df1.merge(df2, how='outer')
  • 左合并、右合并:how=‘left’,how=‘right’
# 左连接: 
df1.merge(df2, how='left')# 右连接: 
df1.merge(df2, how='right')

添加后缀

  • 当列冲突时,即有多个列名称相同时,需要使用on=来指定哪一个列作为key,配合suffixes指定冲突列名
  • 可以使用suffixes=自己指定后缀
df1 = pd.DataFrame({'name': ['张三', '李四', '王五'],'id' : [1, 2, 3],'age': [22, 33, 44]
})
df2 = pd.DataFrame({'id' : [2, 3, 4],'name': ['李四', '王五', '赵六'],'job': ['saler', 'CTO', 'Programer']
})
display(df1, df2)df1.merge(df2, on='id', suffixes=['_表1', '_表2'])

merge合并总结

  • 合并有三种现象: 一对一, 多对一, 多对多.
  • 合并默认会找相同的列名进行合并, 如果有多个列名相同,用on来指定.
  • 如果没有列名相同,但是数据又相同,可以通过left_on, right_on来分别指定要合并的列.
  • 如果想和index合并, 使用left_index, right_index来指定.
  • 如果多个列相同,合并之后可以通过suffixes来区分.
  • 还可以通过how来控制合并的结果, 默认是内合并, 还有外合并outer, 左合并left, 右合并right.

Pandas缺失值处理

None

  • None是Python自带的,是Python中的空对象。None不能参与到任何计算中。

  • object类型的运算要比int类型的运算慢得多

# 计算不同数据类型求和时间
%timeit np.arange(1e5, dtype=object).sum()
# 6.1 ms ± 122 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)%timeit np.arange(1e5, dtype=np.int32).sum()
# 134 µs ± 7.16 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

np.nan(NaN)

  • np.nan是浮点类型,能参与到计算中。但计算的结果总是NaN。
type(np.nan)
# float
  • 但可以使用np.nan*()函数来计算nan,此时会过滤掉nan。
n = np.array([1, 2, 3, np.nan, 5, 6])# np.sum(n)  # nan
np.nansum(n)np.nan + 10

pandas中的None与NaN

pandas中None与np.nan都视作np.nan

  • 创建DataFrame
data = np.random.randint(0 ,100, size=(5, 5))
df = pd.DataFrame(data=data, columns=list('ABCDE'))# 修改数据,增加2种nan
df.loc[2, 'B'] = np.nan
df.loc[3, 'C'] = None
display(df)# 查看结果
df.loc[2, 'B']  # nan
df.loc[3, 'C']  # nan

pandas中None与np.nan的操作

  • isnull()
  • notnull()
  • all()
  • any()
  • dropna(): 过滤丢失数据
  • fillna(): 填充丢失数据

(1)判断函数

  • isnull()
  • notnull()
# isnull
df.isnull()# notnull
df.notnull()# all(): 必须全部为True才为True, 类似and
# any(): 只要有一个为True即为True,  类似ordf.isnull().any()  # 常用, 尽可能找到所有的空值
# df.isnull().all()df.notnull().all()  # 常用,尽可能找到所有的空值
# df.notnull().any()df.isnull().any(axis=1)  # axis=1 表式列,判断一行中的每一列数据进行判断
df.notnull().all(axis=1)
  • 使用bool值索引过滤数据
# 行过滤
# 将df中有空的列过滤掉
cond = df.isnull().any(axis=1)
# display(cond, ~cond)
# ~ 取反
df[~cond]cond = df.notnull().all(axis=1)
# cond
df[cond]# 列过滤
cond = df.notnull().all()
# cond
df.loc[:, cond]cond = df.isnull().any()
# cond
df.loc[:, ~cond]

(2) 过滤函数

  • dropna()

可以选择过滤的是行还是列(默认为行)

df.dropna()  # 默认是删除有空的行
df.dropna(axis=1)  # 删除有空的列

也可以选择过滤的方式 how = ‘all’

df.dropna(how='any')  # 默认值,默认有空就会删除
df.dropna(how='all', axis=1)  # 所有的值都为空(整行或整列为空),才删除

inplace=True 修改原数据

df2 = df.copy()# inplace=True: 表式修改原数据
df2.dropna(inplace=True)
df2

(3) 填充函数 Series/DataFrame

  • fillna()
# 填充
df.fillna(value=100)df2 = df.copy()
df2.loc[1, 'B'] = np.nan
df2.loc[4, 'C'] = None
display(df2)# limit: 限制对应维度上填充的次数
df2.fillna(value=100, limit=1, inplace=True)# 可以选择前向填充还是后向填充
# method : {'backfill', 'bfill', 'pad', 'ffill', None}, default None
#     Method to use for filling holes in reindexed Series
#     pad/ffill: propagate last valid observation forward to next valid
#     backfill/bfill: use next valid observation to fill gap.df.fillna(method='ffill')  # 用上面数据来填充自己
# df.fillna(method='pad')df.fillna(method='bfill')  # 用下面数据来填充自己
# df.fillna(method='backfill')df.fillna(method='ffill', axis=1)  # 用左边数据来填充自己df.fillna(method='bfill', axis=1)  # 用右边数据来填充自己

Pandas处理重复值和异常值

删除重复行

  • 使用duplicated()函数检测重复的行,返回元素为布尔类型的Series对象
  • 每个元素对应一行,如果该行不是第一次出现,则元素为True
# 让第一行和第二行重复
df.loc[1] = df.loc[2]# 判断是否和前面的行重复了
df.duplicated()# df.duplicated(keep='first')  # 保留第一行
# df.duplicated(keep='last')  # 保留最后一行
# df.duplicated(keep=False)  # 标记所有重复行df.loc[1, 'D'] = 'DDD'
# subset: 子集, 只需要子集相同就可以判断重复
df.duplicated(subset=['A', 'B', 'C'])

使用drop_duplicates()函数删除重复的行

df.drop_duplicates(subset=['A', 'B', 'C'])
df.drop_duplicates(subset=['A', 'B', 'C'], keep='last')

映射

映射的含义:创建一个映射关系列表,把values元素和一个特定的标签或者字符串绑定

包含三种操作:

  • replace()函数:替换元素
  • map()函数:处理某一单独的列, 最重要
  • rename()函数:替换索引

replace()函数:替换元素

使用replace()函数,对values进行替换操作

index = ['鲁班', '张三丰', '张无忌', '杜甫', '李白']
columns = ['Python', 'Java', 'H5', 'Pandas']
data = np.random.randint(0, 100, size=(5, 4))df = pd.DataFrame(data=data, index=index, columns=columns)# replace还经常用来替换NaN元素
df.replace({1: 100})

map()函数:

适合处理某一单独的列

df2 = df.copy()
df2# map是Series调用,不能使用DataFrame调用
df2['Python'].map({12: 100, 11: 90})# map()函数中可以使用lambda函数
# 新建一列
df2['NumPy'] = df2['Python'].map(lambda x: x+100)
df2# 新增一列:判断java成绩是否及格
df2['是否及格'] = df2['Java'].map(lambda n:  "及格" if n>=60 else "不及格")
df2# 新增一列:判断Java成绩的等级(>=80优秀,>=60及格,<60不及格)
def fn(n):if n >= 80:return '优秀'elif n >= 60:return '及格'return '不及格'df2['等级'] = df2['Java'].map(fn)
df2

rename()函数:替换索引

df3 = df.copy()
df3# 更改索引名称
df3.rename({'鲁班': "Mr Lu"})  # 默认更改行索引
df3.rename({'Python': 'PYTHON'}, axis=1)  # 更改列索引df3.rename(index={'鲁班': "Mr Lu"})  # 更改行索引
df3.rename(columns={'Python': 'PYTHON'})  # 更改列索引

apply()函数:

既支持 Series,也支持 DataFrame

df = pd.DataFrame(data=np.random.randint(0, 10, size=(5,3)),index=list('ABCDE'),columns=['Python', 'NumPy', 'Pandas'])# 用于Series,其中x是Series中元素
df['Python'].apply(lambda x:True if x >5 else False) # 用于DataFrame,其中的x是DataFrame中列或者行,是Series
df.apply(lambda x : x.median(), axis=0)  # 列的中位数
df.apply(lambda x : x.median(), axis=1)  # 行的中位数# 自定义方法
def convert(x): return (np.round(x.mean(), 1), x.count())
df.apply(convert, axis=1)  # 行平均值,计数# applymap: DataFrame专有, 其中的x是DataFrame中每个元素
df.applymap(lambda x : x + 100) # 计算DataFrame中每个元素

transform()函数

df = pd.DataFrame(data=np.random.randint(0, 10, size=(10,3)),index=list('ABCDEFHIJK'),columns=['Python', 'NumPy', 'Pandas'])# 1、一列执行多项计算
df['Python'].transform([np.sqrt, np.exp]) # Series处理# 2、多列执行不同计算
def convert(x):if x.mean() > 5:x *= 10else:x *= -10return xdf.transform({'Python':convert,'NumPy':np.max,'Pandas':np.min}) 

异常值检测和过滤

  • describe(): 查看每一列的描述性统计量
# 查看每一列的描述性统计
df.describe()
df.describe([0.3, 0.4, 0.5, 0.9, 0.99])  # 指定百分位数
df.describe([0.3, 0.4, 0.5, 0.9, 0.99]).T  # 转置,行和列转换,在列比较多的情况下使用
  • df.std() : 可以求得DataFrame对象每一列的标准差
df.std()
  • df.drop(): 删除特定索引
df4 = df.copy()
df4df4.drop('鲁班')  # 默认删除行
df4.drop('Java', axis=1)  # 删除列df4.drop(index='鲁班')  # 删除行
df4.drop(columns='H5')  # 删除列df4.drop(columns=['Java', 'Pandas'])  # 同时删除多列
  • unique() : 唯一,去重
index = ['鲁班', '张三丰', '张无忌', '杜甫', '李白']
columns = ['Python', 'Java', 'H5', 'Pandas']
data = np.random.randint(0, 10, size=(5, 4))df = pd.DataFrame(data=data, index=index, columns=columns)
df# unique() : 要用于Series, 不能用于DataFrame
df['Python'].unique()
  • query() : 按条件查询
# ==, >, <, 
# in
# and &
# or  |df.query('Python == 5')
df.query('Python > 5')df.query('Python==5 and Java==5')
df.query('Python==5 & Java==5')
df.query('Python==5 or Java==6')
df.query('Python==5 | Java==6')# 使用变量
n = 5
df.query('Python > @n')  # @n 使用变量
df.query('Python in [3, 4, 5, 6]')
m = [3, 4, 5, 6]
df.query('Python in @m')
  • df.sort_values(): 根据值排序

  • df.sort_index(): 根据索引排序

index = ['鲁班', '张三丰', '张无忌', '杜甫', '李白']
columns = ['Python', 'Java', 'H5', 'Pandas']
data = np.random.randint(0, 100, size=(5, 4))df = pd.DataFrame(data=data, index=index, columns=columns)
dfdf.sort_values('Python')  # 默认按照列名排序,默认升序
df.sort_values('Python', ascending=False)    # 降序
df.sort_values('鲁班', axis=1)  # 按照行索引或列索引排序
df.sort_index(ascending=True, axis=1)
  • df.info(): 查看数据信息
df.info()

抽样

  • 使用.take()函数排序

  • 可以借助np.random.permutation()函数随机排序

# 使用前面的df2
df2.take([4, 1, 2, 3, 0])   # 行排列
df2.take([1, 0, 2, 3, 4, 5, 6], axis=1)  # 列排列# 随机排序
np.random.permutation([0, 1, 2, 3, 4, 5])# 无放回抽样:依次拿取,没有重复值
df2.take(np.random.permutation([0, 1, 2, 3, 4]))# 有放回抽样: 可能出现重复值
# 当DataFrame规模足够大时,直接使用np.random.randint()函数,就配合take()函数实现随机抽样
np.random.randint(0, 10, size=10)
df2.take(np.random.randint(0, 5, size=5))

Pandas数学函数

  • 聚合函数
df = pd.DataFrame(data=np.random.randint(0,100,size = (20,3)))df.count() # 非空值的数量
df.max() # 最大值,axis=0/1
df.min() # 最小值, axis=0/1
df.median() # 中位数
df.sum() # 求和
df.mean(axis=1) # 每一行的平均值df[0].value_counts() # 统计元素出现次数
df.cumsum() # 累加
df.cumprod() # 累乘# 方差: 当数据分布比较分散(即数据在平均数附近波动较大)时,各个数据与平均数的差的平方和较大,方差就较大;当数据分布比较集中时,各个数据与平均数的差的平方和较小。因此方差越大,数据的波动越大;方差越小,数据的波动就越小
df.var() # 方差# 标准差 = 方差的算术平方根
df.std() # 标准差

其他数学函数

协方差
- 两组数值中每对变量的偏差乘积的平均值
- 协方差>0 : 表式两组变量正相关
- 如果两个变量的变化趋势一致,也就是说如果其中一个大于自身的期望值时另外一个也大于自身的期望值,那么两个变量之间的协方差就是正值;
- 协方差<0 : 表式两组变量负相关
- 如果两个变量的变化趋势相反,即其中一个变量大于自身的期望值时另外一个却小于自身的期望值,那么两个变量之间的协方差就是负值。
- 协方差=0 : 表式两组变量不相关

相关系数

  • 相关系数r = X与Y的协方差 / (X的标准差 * Y的标准差)
  • 相关系数值的范围在-1和+1之间
  • r>0为正相关,r<0为负相关。r=0表示不相关
  • r 的绝对值越大,相关程度越高
  • 两个变量之间的相关程度,一般划分为四级:
    • 如两者呈正相关,r呈正值,r=1时为完全正相关;
    • 如两者呈负相关则r呈负值,而r=-1时为完全负相关,完全正相关或负相关时,所有图点都在直线回归线上;点分布在直线回归线上下越离散,r的绝对值越小。
    • 相关系数的绝对值越接近1,相关越密切;越接近于0,相关越不密切。
    • 当r=0时,说明X和Y两个变量之间无直线关系。
    • 通常|r|大于0.8时,认为两个变量有很强的线性相关性。
# 协方差
#   两组数值中每对变量的偏差乘积的平均值df.cov() 
df[0].cov(df[1])  # 第0列 和 第1列的协方差# 相关系数 = X与Y的协方差 / (X的标准差 * Y的标准差)
df.corr() # 所有属性相关性系数
df.corrwith(df[2]) # 单一属性相关性系数

协方差: C o v ( X , Y ) = ∑ 1 n ( X i − X ‾ ) ( Y i − Y ‾ ) n − 1 Cov(X,Y) = \frac{\sum\limits_1^n(X_i - \overline{X})(Y_i - \overline{Y})}{n-1} Cov(X,Y)=n11n(XiX)(YiY)

相关性系数: r ( X , Y ) = C o v ( X , Y ) V a r [ X ] ∗ V a r [ Y ] r(X,Y) = \frac{Cov(X,Y)}{\sqrt{Var[X]*Var[Y]}} r(X,Y)=Var[X]Var[Y] Cov(X,Y)

数据分组聚合

数据聚合是数据处理的最后一步,通常是要使每一个数组生成一个单一的数值。

分组

数据聚合处理:

  • 分组:先把数据分为几组
  • 用函数处理:为不同组的数据应用不同的函数以转换数据
  • 合并:把不同组得到的结果合并起来

数据分类处理的核心: groupby()函数

# 创建DataFrame
df = pd.DataFrame({'color': ['green', 'green', 'yellow', 'blue', 'blue', 'yellow', 'yellow'],'price': [4, 5, 3, 2, 7, 8, 9]}
)
df# 使用.groups属性查看各行的分组情况:
# 根据color进行分组
df.groupby(by='color')
df.groupby(by='color').groups# 分组 + 聚合
df.groupby(by='color').sum()
分组聚合练习:

假设菜市场张大妈在卖菜,有以下属性:

  • 菜品(item):萝卜,白菜,辣椒,冬瓜

  • 颜色(color):白,青,红

  • 重量(weight)

  • 价格(price)

  1. 要求以属性作为列索引,新建一个ddd
  2. 对ddd进行聚合操作,求出颜色为白色的价格总和
  3. 对ddd进行聚合操作,求出萝卜的所有重量以及平均价格
  4. 使用merge合并总重量及平均价格
ddd = pd.DataFrame(data={"item": ["萝卜","白菜","辣椒","冬瓜","萝卜","白菜","辣椒","冬瓜"],'color':["白","青","红","白","青","红","白","青"],'weight': [10,20,10,10,30,40,50,60],'price': [0.99, 1.99, 2.99, 3.99, 4, 5, 6,7]}
)
ddd# 2. 对ddd进行聚合操作,求出颜色为白色的价格总和
ddd.groupby('color')['price'].sum()  # Series
ddd.groupby('color')[['price']].sum()  # DataFrame
ddd.groupby('color')[['price']].sum() .loc[['白']]# 3. 对ddd进行聚合操作,求出萝卜的所有重量以及平均价格
df1 = ddd.groupby('item')[['weight']].sum()
df2= ddd.groupby('item')[['price']].mean()# 4.使用merge合并总重量及平均价格
# display(df1, df2)
df1.merge(df2, left_index=True, right_index=True)

Pandas加载数据

csv数据

data = np.random.randint(0,50,size=(10,5))
df = pd.DataFrame(data=data, columns=['Python','Java','Go','C','JS'])# 保存到csv
df.to_csv('data.csv',sep=',',  # 文本分隔符,默认是逗号header=True, # 是否保存列索引# 是否保存行索引,保存行索引,文件被加载时,默认行索引会作为一列index=True)  # 加载csv数据
pd.read_csv('data.csv',sep=',', # 默认是逗号header=[0], # 指定列索引index_col=0)  # 指定行索引pd.read_table('data.csv', # 和read_csv类似,读取限定分隔符的文本文件sep=',',header=[0], # 指定列索引index_col=0  # 指定行索引) 

excel数据

data = np.random.randint(0, 50, size=(10,5))
df = pd.pDataFrame(data=data, columns=['Python','Java','Go','C','JS'])# 保存到excel文件
df.to_excel('data.xls',sheet_name='sheet1',# Excel中工作表的名字header=True, # 是否保存列索引index=False) # 是否保存行索引# 读取excel
pd.read_excel('data.xls',sheet_name=0, # 读取哪一个Excel中工作表,默认第一个, 也可以写工作表名称header=0, # 使用第一行数据作为列索引names=list('ABCDE'), # 替换行索引index_col=1) # 指定行索引,B作为行索引

MySQL数据

  • 需要安装pymysql
    • pip install pymysql -i https://pypi.tuna.tsinghua.edu.cn/simple
  • 需要安装sqlalchemy:
    • pip install sqlalchemy -i https://pypi.tuna.tsinghua.edu.cn/simple
    • sqlalchemy是Python语言下的数据库引擎库, 在Django/Flask中常用ORM库
from sqlalchemy import create_enginedata = np.random.randint(0,150,size=(150,3))
df = pd.DataFrame(data=data, columns=['Python','Pandas','PyTorch'])# 数据库连接
# root: MySQL用户名
# 123456: MySQL密码
# localhost: 本机
# db: 数据库名(提前创建)
conn = create_engine('mysql+pymysql://root:123456@localhost/db')# 保存到MySQL
df.to_sql('score', # 表名(会自动创建表)conn, # 数据库连接index=False,  # 是否保存行索引if_exists='append') # 如果表名存在,追加数据# 从MySQL中加载数据
pd.read_sql('select * from score', # sql查询语句conn, # 数据库连接index_col='Python') # 指定行索引名

Pandas分箱操作

  • 分箱操作就是将连续型数据离散化。
  • 分箱操作分为等距分箱和等频分箱。
data = np.random.randint(0,150,size=(150,3))
df = pd.DataFrame(data=data, columns=['Python','Pandas','PyTorch'])# 对Python列进行分箱
df.Python.values# 1、等宽分箱
pd.cut(df.Python, bins=4)# 指定宽度分箱
pd.cut(df.Python, # 分箱数据bins=[0, 30, 60, 80, 100], # 分箱断点right=False, # 左闭右开labels=['D','C','B','A']) # 分箱后分类标签# 2、等频分箱
pd.qcut(df.Python, # 分箱数据q=4, # 4等份labels=['差', '中', '良', '优']) # 分箱后分类标签

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/38420.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

光照老化试验箱:材料耐久性的“时间加速器”

光照老化试验箱&#xff1a;材料耐久性的“时间加速器”概述 光照老化试验箱是一种模拟自然光照条件下材料老化过程的设备&#xff0c;广泛应用于材料科学领域的耐久性能评估。通过模拟日光中的紫外线、热辐射等环境因素&#xff0c;加速材料老化过程&#xff0c;以此来验证材…

redhawk:tech file与lefdef layer name不匹配问题

我正在「拾陆楼」和朋友们讨论有趣的话题&#xff0c;你⼀起来吧&#xff1f; 拾陆楼知识星球入口 一些工艺厂商给的redhawk tech file是加密的&#xff0c;读完tech file再读lef/def会报错&#xff0c;根本不知道问题在哪&#xff0c;他们一般会搭配给一个layer map&#xff…

分解+降维+预测!多重创新!直接写核心!EMD-KPCA-Transformer多变量时间序列光伏功率预测

分解降维预测&#xff01;多重创新&#xff01;直接写核心&#xff01;EMD-KPCA-Transformer多变量时间序列光伏功率预测 目录 分解降维预测&#xff01;多重创新&#xff01;直接写核心&#xff01;EMD-KPCA-Transformer多变量时间序列光伏功率预测效果一览基本介绍程序设计参…

【简单讲解神经网络训练中batch的作用】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

Maven依赖解析过程详细讲解

Maven依赖解析是一个递归的过程&#xff0c;涉及从项目的POM文件开始&#xff0c;逐步解析直接依赖和传递依赖。以下是详细的解析过程&#xff1a; 读取项目的POM文件&#xff1a; Maven首先读取项目的POM文件 (pom.xml)&#xff0c;该文件定义了项目的直接依赖。 解析直接依赖…

STM32第十五课:LCD屏幕及应用

文章目录 需求一、LCD显示屏二、全屏图片三、数据显示1.显示欢迎词2.显示温湿度3.显示当前时间 四、需求实现代码 需求 1.在LCD屏上显示一张全屏图片。 2.在LCD屏上显示当前时间&#xff0c;温度&#xff0c;湿度。 一、LCD显示屏 液晶显示器&#xff0c;简称 LCD(Liquid Cry…

node_sqlite3.node is not a valid win32 application

electron打包报错 使用electron在linux平台打包含有sqlite3的项目为win32应用时在运行阶段&#xff0c;有时会遇到下面的错误 node_sqlite3.node is not a valid win32 application出现该错误的原因主要是在64bit的linux环境中&#xff0c;sqlite3默认build出来的二进制文件不…

【Windows】Visual Studio Installer下载缓慢解决办法

【Windows】Visual Studio Installer下载缓慢解决办法 1.背景2.分析3.结果 1.背景 使用visual studio在线安装包进行IDE安装&#xff0c;发现下载几乎停滞&#xff0c;网速几乎为零。 经过排查并不是因为实际网络带宽导致。 这里涉及DNS知识&#xff1b; DNS&#xff08;Dom…

消防认证-防火卷帘

一、消防认证 消防认证是指消防产品符合国家相关技术要求和标准&#xff0c;且通过了国家认证认可监督管理委员会审批&#xff0c;获得消防认证资质的认证机构颁发的证书&#xff0c;消防产品具有完好的防火功能&#xff0c;是住房和城乡建设领域验收的重要指标。 二、认证依据…

TP8 JS(html2canvas) 把DIV内容生成二维码并与背景图、文字组合生成分享海报

方法一&#xff1a;前端JS生成(推荐) 注意&#xff1a; 1.这个网页只能截图图片效果代码&#xff0c;其它任何html效果都不能有&#xff0c;不然截图就不准确 2.如果要生成的图片DIV内容中引用了第三个方的图片&#xff0c;就是不使用同一个域名下的图片&#xff0c;需要把后…

Python爬取淘宝商品评价信息实战:从零到一的高效教程

引言&#xff1a;揭秘淘宝数据金矿 在电商领域&#xff0c;用户评价是衡量产品优劣的金标准。作为Python爬虫工程师&#xff0c;掌握从淘宝这座数据金矿中挖掘宝贵评价信息的技能至关重要。本文将带你手把手实操&#xff0c;用Python爬虫技术获取淘宝商品的评价信息&#xff0…

Docker多阶段构建Node.js应用程序

Node.js 应用程序 创建一个目录来存放你的项目文件&#xff0c;然后在该目录下创建以下文件。 package.json {"name": "docker-node-test","version": "1.0.0","description": "A simple Node.js app for Docker mu…

【折腾笔记】使用 PicList + Lsky Pro 对图片进行双重压缩

前言 因为服务器的带宽比较小,为了提高网站的访问速度,网站内的图片进行压缩是必不可少的。另外将图片转换成WebP的格式可以减小文件大小、加快加载速度、支持高级特性(如透明度和动画),以及减少存储需求,为网站提供了显著的性能。需要提前安装好PicList客户端和Lsky Pr…

最快33天录用!一投就中的医学4区SCI,几乎不退稿~

【SciencePub学术】今天小编给大家推荐2本生物医学领域的SCI&#xff0c;此期刊为我处目前合作的重点期刊&#xff01;影响因子0-3.0之间&#xff0c;最重要的是审稿周期较短&#xff0c;对急投的学者较为友好&#xff01; 医学医药类SCI 01 / 期刊概况 【期刊简介】IF&…

那些好用的 Vue3 的工具搭子!!【送源码】

2020 年 9 月 18 日 Vue3 的正式发布已经过去了大约 3 年 9 个月左右&#xff01;&#xff01;&#xff01; 随着 Vue3 版本的逐渐成熟&#xff0c;我们的前端世界也迎来了一系列令人振奋的更新和工具。Vue 生态圈的持续扩大&#xff0c;无疑为前端开发人员带来了前所未有的便…

通过pycharm使用git和github的步骤

一、在Pycharm工具中配置集成Git和GitHub。 1.集成Git。 打开Pycharm, 点击File-->Settins-->Version Control-->Git 然后在 Path to Git executable中选择本地的git.exe路径。如下图&#xff1a; 2.集成GitHub 打开Pycharm, 点击File-->Settins-->Version…

探索未来远程调试新纪元——《串口网口远程调试软件》:无缝连接,高效调试

文章目录 前言一、无缝连接&#xff0c;突破距离限制二、高效调试&#xff0c;提升工作效率三、安全可靠&#xff0c;保护数据安全四、用户友好&#xff0c;简化操作流程五、软件地址六、远程调试软件 七、基本操作1、订阅主题2、连接3、串口调试4、网口调试 八、软件地址结束语…

PO模式登录测试

项目实践 登陆项目测试 get_driver import page from selenium import webdriverclass GetDriver:driver Noneclassmethoddef get_driver(cls):if cls.driver is None:cls.driver webdriver.Edge()cls.driver.maximize_window()cls.driver.get(page.url)return cls.drivercl…

Java高风险漏洞与修复之——LDAP injection(LDAP注入)

LDAP注入介绍 LDAP注入是一种攻击技术,它可以利用应用程序中的安全漏洞对LDAP(轻量级目录访问协议)服务进行恶意查询或修改操作。当应用程序未能适当地清理用户的输入内容,将其嵌入到LDAP查询中时,就可能发生LDAP注入。攻击者通过注入未经授权的指令或条件来操纵查询结果…

【代码随想录训练营】【Day 66】【图论-3】| 卡码 101-104

【代码随想录训练营】【Day 66】【图论-3】| 卡码 101-104 需强化知识点 103&#xff0c;104 优化思路 题目 101. 孤岛的总面积 此处 area 多余 def dfs(grid, x, y, area):dirs [[0, 1], [0, -1], [1, 0], [-1, 0]]m, n len(grid), len(grid[0])area[0] 1grid[x][y] …