添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
首发于 学习记录

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 = 1center = Falseaxis = 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(exprinplace = False** kwargs)
  • 参数: -- expr:str要评估的查询字符串。你可以在环境中引用变量,在它们前面添加一个'@'字符 。@a + b -- inplace=False:是否修改数据或返回副本 -- kwargs:dict关键字参数

(1) 计算三月份('month ==3')的平均值

df['year'] = df['createTime'].apply(lambda x: x.year)