python学习笔记(三)
Numpy和Pandas(二)
Pandas
基础操作
1. 创建DataFrame
data = {"grammer":['Python', 'C', 'Java', 'R', 'SQL', 'PHP', 'Python', 'Java', 'C', 'Python'],
"score":[6, 2, 6, 4, 2, 5, 8, 10, 3, 4],
"cycle":[4, 2, 6, 2, 1, 2, 2, 3, 3, 6]}
df = pd.DataFrame(data)
2. 查看前/后5行数据
df.head() # 默认为5
df.tail(5) # 不填的话默认为5
3. 查看所有列名
df.columns
4. 查看数据框行列数/行数/列数
df.shape # 行列数(10, 3)
df.shape[0]#行数
len(df)#行数
df.shape[1]#列数
5.查看数据类型和内存信息
df.info()
输出结果:
6.查看索引
df.index
7.查看数值型列的汇总统计
df.describe()
8.查看每列的数据类型
df.dtypes
9.查看某列共有几种元素
len(df['grammer'].unique())
10. 查看某一列各元素出现的次数
df['grammer'].value_counts()
11.查看某列每个字符串的长度
# 方法一:
df['grammer'].str.len()
# 方法二:
df['grammer'].map(lambda x: len(x))
数据框行列操作及数据读取与保存
1. 设置索引
df['new_index'] = range(1,11)
df.set_index('new_index')
2.重置索引(行号)
df.reset_index(drop = True, inplace = True)
# drop = True:原有索引就不会成为新的列
3.改列名
#方法一:直接法
df.columns = ['grammer', 'score', 'cycle', 'id']
#方法二:(使用rename()函数:修改指定修改某列或某几列名字)
df.rename(columns={'col1':'grammer', 'col2':'score', 'col3':'cycle','new_index':'id'}, inplace=True)
4. 调整列顺序
(1) 将所有列倒序排列
#方法一:
df.iloc[:, ::-1]
df.iloc[:, [-1,-2,-3,-4]]
(2) 交换两列位置
temp = df['grammer']
df.drop(labels=['grammer'], axis=1, inplace=True)
df.insert(1, 'grammer', temp)
(3) 更改全部列顺序
order = df.columns[[0, 3, 1, 2]] # 或者order = ['xx', 'xx',...] 具体列名
df = df[order]
6. 删除行列
(1) 删除id这一列
# 法一:
del df['id']
# 法二:
df.drop('id',axis=1, inplace=True) #columns=['xxx']
(2) 添加一行grammer='css'数据,并删除该行
df.loc[len(df)] = [2, 'css', 3]
index = df[df['grammer'] == 'css'].index[0]
df.drop(labels=[index], inplace=True)
7.将grammer列和score列合并成新的一列
df['new_col'] = df['grammer'] + df['score'].map(str) # score为int类型,需转换为字符串类型;
8.将数据按行的方式逆序输出
df.iloc[::-1, :]
# [::-1]表示步长为-1, 从后往前倒序输出
9.数据读取与保存
(1.读取
excel = pd.read_excel('/home/pandas_task6584/pandas120.xlsx')
csv = pd.read_csv('/home/pandas_task6584/pandas120.csv')
tsv = pd.read_csv('/home/pandas_task6584/pandas120.tsv', sep = '\t')
(2.读取时设置显示行列的参数:pd.set_option()
(1) 显示所有列
pd.set_option('display.max_columns', None)
pd.set_option('display.max_columns', 5) #最多显示5列
(2) 显示所有行
pd.set_option('display.max_rows', None)
pd.set_option('display.max_rows', 10)#最多显示10行
(3) 显示小数位数
pd.set_option('display.float_format',lambda x: '%.2f'%x) #两位
(4) 显示宽度
pd.set_option('display.width', 100)
(5) 设置小数点后的位数
pd.set_option('precision', 1)
(6) 是否换行显示
pd.set_option('expand_frame_repr', False)
# True就是可以换行显示。设置成False的时候不允许换行
(3.保存
df.to_csv('course.csv')
数据提取
1.提取指定行列的数据
(1) 提取第32行数据
# 方法一:
df.loc[32]
# 方法二:
df.iloc[32,:] # df.iloc[32] 也可
(2)提取education这一列数据
#方法一
df['education']
data.iloc[:,1]
(3) 提取后两列(education, salary)数据
# 方法一:
df[['education', 'salary']]
# 方法二:
df.iloc[:, 1:]
df[['education', 'salary']]和df['education', 'salary']不一样
(4) 提取第一列位置在1,10,15上的值
# 方法一:
df.iloc[[1,10,15], 0]
# 方法二:
df['createTime'][[1,10,15]]
# 方法三:
df['createTime'].take([1,10,15])
2. 提取重复值所在的行列数据
(1) 判断createTime列数据是否重复
df.createTime.duplicated()
(2) 判断数据框中所有行是否存在重复
df.duplicated()
(3) 判断education列和salary列数据是否重复(多列组合查询)
df.duplicated(subset = ['education','salary'])
3. 按指定条件提取元素值
#加一列
import random
df['value'] = [random.randint(1,100) for i in range(len(df))]
(1) 提取value列元素值大于90的行
df[df['value'] > 60]
(2) 提取value列元素值大于60小于70的行
df[(df['value'] > 60) & (df['value'] < 70)]
(3) 提取某列最大值所在的行
df[df['value'] == df['value'].max()]
(4) 提取value和value1之和大于150的最后三行
# 再随机生成一列1到100内的随机数
data[value1] = [random.randint(1,100) for i in range(135)]
df[(df['value'] + df['value1']) > 150].tail(3)
4. 提取含空值的行列
#为了演示,更改一些值;
df.loc[[2,10,45,87], 'value'] = np.nan
df.loc[[19,30,55,97,114], 'value1'] = np.nan
df.loc[[24,52,67,120], 'education'] = 111
df.loc[[8,26,84], 'salary'] = '--'
(1) 提取value列含有空值的行
df[df['value'].isnull()]
(2) 提取每列缺失值的具体行数
for columname in df.columns: #遍历每一列
if df[columname].count() != len(df): #判断缺失行条件:所在列的值数等于总数据的长度
#将存在缺失值的行的索引转换成列表储存
loc = df[columname][df[columname].isnull().values == True].index.tolist()
print('列名:"{}",第{}行位置有缺失值'.format(columname, loc))
5. 提取某列不是数值或(包含)字符串的行
(1) 提取education列数值类型不是字符串的行
temp = pd.DataFrame()
for i in range(len(df)):
if type(df['education'][i]) != str: #df['xxx'][i]或写成df.iloc[i,j]
temp = temp.append(df.loc[i])
(2) 提取salary列包含字符串('--')的行
# 方法一:isin()
df[df['salary'].isin(['--'])]
# 方法二:contains()
df[df["salary"].str.contains("--")]
(3) 提取education列值为'硕士'的
# 方法一:
df[df['education'] == '硕士']
# 方法二:
results = df['education'].str.contains('硕士')
results.fillna(value=False, inplace=True)
df[results]
6. 提取学历为本科和硕士的数据,只显示学历和薪资两列
# 方法一:isin()
df[df['education'].isin(['本科', '硕士'])] [['education', 'salary']]
# 方法二:loc提取
df.loc[df['education'].isin(['本科', '硕士']), ['education', 'salary']]
7. 提取salary列以'25k'开头的行
# 方法一:match函数
df[df['salary'].str.match('25k')]
# 方法二:startswith函数
df[df['salary'].str.startswith('25k')]
8. 提取value列中不在value1列出现的数字
df['value'][~df['value'].isin(df['value1'])] #~取反
9. 提取value列和value1列出现频率最高的数字
# 先将两列使用append()按行合并,再用计数函数:
temp = df['value'].append(df['value1'])
temp.value_counts(ascending=False)#不加index,返回的是一个Series
temp.value_counts(ascending=False).index[:5] #返回一个数组
10. 提取value列中可以整除10的数字位置
#方法一:
df[df['value'] % 10 == 0].index
#方法二:np.argwhere
np.argwhere(np.array(df['value'] % 10 == 0))
数据处理
1. 缺失值处理
(1) 判断缺失值
# 检查数据中是否含有任何缺失值:
df.isnull().values.any()
df.isnull()#返回的是一个值为True或者False的dateframe
df.isnull().values# 是一个值为True或者False的array
df.isnull().any()
结果:每列是否有空值
createTime False
education False
salary False
value True
value1 True
dtype: bool'''
# 查看每列数据缺失值:
df.isnull().sum()
# 查看每列非缺失值数:
df.notnull().sum()
df.shape[0] - df.isnull().sum()
(2) 缺失值填充
# 用上下平均值填充value列:
df['value'] = df['value'].fillna(df['value'].interpolate())
df.head()
# df (注意赋值,如果不赋值,原始序列未改变)
# 将value列缺失值全部替换为1.0:
df.fillna(value =1.0, inplace = True)
(3) 更改缺失值
# 将value列第10行到13行设置为缺失值:
df.loc[9:12,'value'] = np.nan
# 将第三行设置为缺失值:
df.loc[:2] = np.nan
(4) 删除缺失值
# 删除所有存在缺失值的行:
df.dropna(axis=0, how='any', inplace=True)
# 删除所有有缺失值的行
df.dropna() # -- 默认axis=0
# 删除所有有缺失值的列
df.dropna(axis='columns')
df.dropna(axis=1)
# 删除所有值缺失的行
df.dropna(how='all')
# 删除至少有两个非缺失值的行
df.dropna(thresh=2)
# 指定判断缺失值的列范围
df.dropna(subset=['education', 'value'])
# 使删除和的结果生效
df.dropna(inplace=True)
# 指定列的缺失值删除
df.value.dropna()
2. 数据去重
# drop_duplicates()
df.drop_duplicates(['createTime'])
3. 添加/删除数据
(1) 添加一行数据['2020-03-16 10:48:36', '硕士', '20k-40k', '43.0']
# 方法一:字典
df2 = pd.DataFrame({
'createTime':['2020-03-16 10:48:36'],
'education':['硕士'],
'salary':['20k-40k'],
'value':[43.0]
df = df.append(df2, ignore_index=True)
df.tail()
# 方法二:loc
df.loc[len(df)] = ['2020-03-16 11:20:41', '硕士', '25k-45k', 29.0]
df.tail()
(2) 删除最后两行数据
df.drop(index=[len(df)-1,len(df)-2], inplace=True)
4. 数据排序
# 按照value列值大小进行排序
df.sort_values(by=['value'], ascending=True) #注:ascending:True升序,False降序
5. 数据类型转换
(1) 设置value2列保留两位小数
# 随机生成一列0.01到1之间的浮点数
df['value2'] = [random.uniform(0.01, 1) for i in range(len(df))]
保留两位小数
# 方法一:round()函数
df['value2'].round(2)
# 方法二:map + lambda
df['value2'].map(lambda x : ('%.2f') % x)
# 方法三:map + lambda + format
df['value2'] = df['value2'].map(lambda x : format(x, '.2f'))
df.head()
(2) 将value2列小数转换为百分数
#由于value2上一步转换为小数时,会自动将浮点类型变为object类型,
df['value2'] = df['value2'].astype('float')
# 方法一:style + 格式化处理
df.style.format({'value2' : '{0:.2%}'.format})
# 方法二:自定义函数+格式化处理
df['value2'] = df['value2'].map(lambda x : format(x, '.2%'))
df.head()
(3) 将value2列数据转换为浮点类型
# 方法一:
df['value2'].str.strip('%').astype('float') # 如果该列存在%符号
# 方法二:
df['value2'].apply(lambda x : float(x[:-1]))
注:apply()和map()区别 1.apply()是一种让函数作用于DataFrame中行或列的操作。 2.applymap()是一种让函数作用于DataFrame每一个元素的操作。 3.map()是一种让函数作用于Series每一个元素的操作。
(4) Series类型转list
# 将value列转换为List类型,只显示10条数据
df['value'].tolist()[:10] # 或者to_list()
(5) 将时间戳类型转换为datatime类型
# 将createTime(第一列)列时间转换为月-日:
for i in range(len(df)):
df.iloc[i,0] = df.iloc[i,0].to_pydatetime().strftime("%m-%d")
df.head()
注:采用Timestamp.to_pydatetime()函数将给定的时间戳转换为本地python datetime对象; strftime()用来格式化datetime 对象
6. 数据拆分
(1) 将salary列按照'-'拆分
df['salary'].str.split('-')
(2) 删除salary列开头和结尾的任何字符,默认为空格
df['salary'].str.strip()
(3)将salary列数据转换为最大值与最小值的平均值
7. 将value列数据开根号
# 方法一:apply() + np.sqrt()
df[['value']].apply(np.sqrt)
# 方法二:map + math.sqrt()
import math
pd.DataFrame(df['value'].map(lambda x : math.sqrt(x)))
数据合并及分组计算
# 创建两个dataframe
data1 = {"course":['Python', 'C', 'Java', 'R', 'SQL'],
"grade":[6, 2, 6, 4, 5],
"cycle":[4, 2, 6, 2, 1]}
data2 = {'course':['Python', 'C', 'PHP', 'R', 'SQL'],
"grade":[6, 2, 6, 4, 5],
'count':[30, 25, 14, 20, 29]}
df = pd.DataFrame(data1)
df1 = pd.DataFrame(data2)
1. 数据合并:concat, merge, append, join
(1) DataFrame.concat()
- 语法:
concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, copy=True)
- 参数: -- objs: series,dataframe或者是panel构成的序列lsit -- axis:需要合并链接的轴,0是行,1是列 -- join:连接的方式 inner,或者outer 只是单纯的把两个表拼接在一起,参数axis是关键,它用于指定合并的轴是行还是列,axis默认是0。
- 例子
# 将第一行与最后一行拼接:
pd.concat([df[:1], df[-2:-1]])
# 将两个dataframe按列合并:
list_ = [random.randint(1, 100) for i in range(len(df))]
df2 = pd.DataFrame(list_, columns=['value'])
pd.concat([df,df2], axis=1) # 按行合并,则axis=0
(2) DataFrame.merge()
- 语法
df = pd.merge(left, right, how = "inner",on = "None")
- 参数: -- left: 左表。也就是第一个df。 -- right:右表。也就是第二个df。 -- how: 和concat里面的"join"类似,表示“如何合并两表。 --- 1)left: 只使用左表的键。 --- 2)right:只使用右表的键。 --- 3)inner: 使用左右表键的交集。 --- 4)outer:使用左右表键的并集。
- on: 表示按照哪一个键来进行合并。 类似于关系型数据库的连接方式,可以根据一个或多个键将不同的DatFrame连接起来。该函数的典型应用场景是,针对同一个主键存在两张不同字段的表,根据主键整合到一张表里面。
- 例子
# 按照单列合并数据:
pd.merge(df, df1, on='course')
# 按照多列合并数据:多列用列表
pd.merge(df, df1, how='left', on=['course', 'grade'])
#内外连接合并:
pd.merge(df, df1, how='outer', on='course') # inner内连接,outer外连接
(3) Series.append()/DataFrame.append()
- 语法:
DataFrame.append(other,ignore_index=False, verify_integrity=False, sort=None)
- 参数: -- other: DataFrame、series、dict、list这样的数据结构 -- ignore_index:默认值为False,如果为True则不使用index标签 -- verify_integrity :默认值为False,如果为True当创建相同的index时会抛出ValueError的异常o sort: boolean,默认是None,该属性在pandas的0.23.0的版本才存在。
- 功能说明: 向dataframe对象中添加新的行,如果添加的列名不在dataframe对象中,将会被当作新的列进行添加
- 例子
# 将第3行数据添加至末尾:
df.append(df.iloc[2])
(4) DataFrame.join()
- 语法:
DataFrame.join(other, on=None, how=’left’, lsuffix=”, rsuffix=”, sort=False)
- 参数: -- other:【DataFrame,或者带有名字的Series,或者DataFrame的list】如果传递的是Series,那么其name属性应当是一个集合,并且该集合将会作为结果DataFrame的列名 -- on:【列名称,或者列名称的list/tuple,或者类似形状的数组】连接的列,默认使用索引连接 -- how:【{‘left’, ‘right’, ‘outer’, ‘inner’}, default:‘left’】连接的方式,默认为左连接 -- lsuffix:【string】左DataFrame中重复列的后缀 -- rsuffix:【string】右DataFrame中重复列的后缀 -- sort:【boolean, default:False】按照字典顺序对结果在连接键上排序。如果为False,连接键的顺序取决于连接类型(关键字)。 主要用于索引上的合并,其参数的意义与merge方法中的参数意义基本一样。该方法最为简单,主要用于索引上的合并
- 例子
df.join(df1, lsuffix='_left', rsuffix='_right')
(5) 总结
- join 最简单,主要用于基于索引的横向合并拼接
- merge 最常用,主要用于基于指定列的横向合并拼接
- concat最强大,可用于横向和纵向合并拼接
- append,主要用于纵向追加
2. 常见统计函数
print('grade列均值:',df['grade'].mean()) # 均值
print('全体平均数:',df.mean().mean()) # 全体平均数
print('grade列中位数:',df['grade'].median()) # 中位数
print('grade列方差:',df['grade'].var()) # 方差
print('grade列标准差:',df['grade'].std()) # 标准差
print('grade列最大值:',df['grade'].max()) # 最大值
print('grade列最小值:',df['grade'].min()) # 最小值
3. diff()函数:计算上下行差值
# 方法一:Series.diff()
df['grade'].diff()
# 方法二:shift(1)
diff = df['grade'] - df['grade'].shift(1)
diff
4. pct_change()函数:计算上下行变化率
# 方法一:Series.pct_change()
df['grade'].pct_change()
# 方法二:shift(1)
df['grade']/df['grade'].shift(1) - 1
5. shift()函数:将数据往后(前)移动x天
df['grade'].shift(2) # 往前移2
df['grade'].shift(-2) # 往后移2
6. rolling()函数:以2个数据作为滑动窗口,取均值/总和
df['grade'].rolling(2).mean()
df['grade'].rolling(2).sum()
7. expanding()函数
- 语法
DataFrame.expanding(min_periods = 1,center = False,axis = 0)
rolling()函数,是固定窗口大小,进行滑动计算; expanding()函数只设置最小的观测值数量,不固定窗口大小,实现累计计算,即不断扩展;
8. agg()函数
- 聚合函数,对分组后数据进行聚合,默认情况对分组后其他列进行聚合
(1) 同时对grade, cycle两列进行计算总和、均值、中位数、最小/大值,标准差、方差;
# 方法一:
df[['grade', 'cycle']].agg([np.sum, np.mean, np.median, np.min, np.max, np.std, np.var])
# 方法二:
df[['grade', 'cycle']].agg(['sum', 'mean', 'median', 'min', 'max', 'std', 'var'])
(2) 对grade列求平均,对cycle列求和
# 方法一:分开再汇总
grade_mean = df['grade'].mean()
cycle_sum = df['cycle'].sum()
grade_mean, cycle_sum
# 方法二:agg()函数
df.agg({'grade' : np.mean, 'cycle' : np.sum})
9. 分组计算
主要的作用是进行数据的分组以及分组后地组内运算
(1) 根据course列元素分组后计算平均值/中位数
df.groupby('course').mean()
df.groupby('course').median()
(2) 按course列分组后,grade列元素最多的是?
# 方法一:head()取行
df[['course', 'grade']].groupby('course').sum().sort_values(by='grade', ascending=False).head(1)
# 方法二:iloc取行
pd.DataFrame(df[['course', 'grade']].groupby('course').sum().sort_values(by='grade', ascending=False).iloc[0,:])
# 方法三:分组后采用agg函数求和
df[['course', 'grade']].groupby('course').agg({'grade':'sum'}).sort_values(by='grade', ascending=False).head(1)
10. query()函数:使用布尔表达式查询帧的列
- 语法:
df.query(expr,inplace = False,** kwargs)
- 参数: -- expr:str要评估的查询字符串。你可以在环境中引用变量,在它们前面添加一个'@'字符 。@a + b -- inplace=False:是否修改数据或返回副本 -- kwargs:dict关键字参数
(1) 计算三月份('month ==3')的平均值
df['year'] = df['createTime'].apply(lambda x: x.year)