回复 红包 可以领程序员专属红包封面
Pandas是一个强大的分析结构化数据的工具集;它的使用基础是Numpy(提供高性能的矩阵运算);
用于数据挖掘和数据分析,同时也提供数据清洗功能。
它是一种类似于一维数组的对象,是由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。
仅由一组数据也可产生简单的Series对象
默认index是数字
import pandas as pd
import numpy as np
# 自定义打印的函数,方便后面调试
def _print(s: str, *args, pad=20):
print('\n', s.center(pad, '-'))
for i in args:
print(i)
infoLi = ['jack', 18, '180CM']
serLi = pd.Series(data=infoLi)
_print('list构建Series', serLi)
serLi = pd.Series(data=infoLi, index=list('abc'))
_print('list构建Series,并指定index', serLi)
index为字典的key
infoDic = {'name': 'jack', 'age': 18, 'height': '180CM'}
serDic = pd.Series(data=infoDic)
_print('字典构建Series', serDic)
infoLi = serLi.tolist()
_print('Series转换为list', infoLi)
infoDic = serDic.to_dict()
_print('Series转换为dict', infoDic)
df = pd.DataFrame(data=serDic)
_print('Series转换为DataFram', df)
df = pd.DataFrame(data=serDic, columns=['信息'])
_print('Series转换为DataFram,并指定列名', df, pad=30)
s = pd.Series(data=['001', '002'], index=list('ab'))
_print('构建Series', s)
sastype = s.astype(int)
_print('使用astype函数修改数据类型', sastype)
map函数可以将一个匿名函数作用于所有的数据上
相当于遍历了一遍Series,对每一个值执行了float()方法
smap = s.map(lambda x: float(x))
smap = s.map(float)
_print('使用map修改数据类型', smap)
使用concat将一个Series追加原Series后面
sCon = pd.Series(data=['003', '004'], index=['c', 'd'])
s = pd.concat([s, sCon])
_print('concat追加新元素', s)
> 指定axis=1,横向追加,两个Series横向追加会变成DataFrame
df = pd.concat([s, sCon], axis=1)
_print('concat追加新元素,并指定axis=1', df)
DataFrame是Pandas中的一个表格型的数据结构,包含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型等),DataFrame即有行索引也有列索引,可以被看做是由Series组成的字典。
> 如果字典的key不是列表,需要指定index,或者使用items()取出k,v
infoDic = {'name': 'jack', 'age': 18, 'height': '180CM'}
df = pd.DataFrame(data=infoDic, index=[0])
_print('指定index=[0]', df)
# 使用items()取出k,v
df = pd.DataFrame(data=list(infoDic.items()))
_print('使用items()取出k,v', df)
infoDic = {'id': [1, 2], 'name': ['jack', 'rose'], 'age': [18, 18], 'height': ['180CM', '170CM']}
df = pd.DataFrame(data=infoDic)
_print('v是列表', df)
columns也可以不指定
df = pd.DataFrame([[1, 2], [11, 12]], columns=['c1', 'c2'], index=['i1', 'i2'])
_print('使用list创建DataFrame', df)
创建一个np.arange()可以创建一维ndarray,reshape是修改形状,这里修改成了3行4列的二维ndarray
同样,直接使用list创建也行
df = pd.DataFrame(np.arange(12).reshape(3, 4))
_print('使用numpy创建DataFrame', df)
index为100个日期,字段内容为正态分布和均匀分布随机数
date_range = pd.date_range(start='2022-01-01', periods=100) # date_rage可以生成各种类型的日期
data = {
'normal': np.random.normal(loc=0, scale=1, size=100), # 正态分布
'uniform': np.random.uniform(low=0, high=1, size=100) # 均匀分布
}
df = pd.DataFrame(data=data, index=date_range)
_print('复杂DataFrame', df)
df = pd.read_csv('./IMDB-Movie-Data.csv')
查看dataframe的描述信息
_print('info', df.info)
查看数据类型
_print('dtypes:', df.dtypes)
df['Title'].astype('string')
查看后面几行
_print('tail', df.tail(10))
查看数据前几行
_print('head', df.head(10))
_print('取单列', df['Rank'])
注意是两个中括号
_print('取多列', df[['Rank', 'Title', 'Metascore']])
可以将列表的切片思想直接拿过来用
_print('按行取', df[0:2])
可同时按照行和列进行取值
_print('loc', df.loc[0:2, 'Rank':'Metascore'])
可同时按照行和列进行取值,使用数字下标
_print('iloc', df.iloc[0:2, 1:3])
所有字符串操作均可以,这里只列举几个
_print('字符串操作', df['Title'].head())
_print('str.upper', df['Title'].str.upper())
_print('str.replace', df['Title'].str.replace(' ', '/'))
_print('str.split', df['Title'].str.split(' '))
如果多个条件,每个条件用()括起来,并且用& 或者用|
print(df[(df['Rank'] % 2 == 0)])
print(df[(df['Rank'] < 10) & (df['Metascore'] > 70)])
df = pd.DataFrame(data=[[1, 2]])
df.columns = ['col1', 'col2']
_print('columns修改所有列名:', df)
df.rename(columns={'col1': 'c1'}, inplace=True)
_print('rename修改指定列名:', df)
df.loc[0, 'c1'] = 11
_print('修改指定值:', df)
df = pd.DataFrame(data=np.full((3, 4), np.nan), columns=list('abcd'), index=list('xyz'))
df.loc['x', 'a'], df.loc['y', 'a'], df.loc['x', 'b'] = 1, 2, 3
print(df)
_print('判断是否为NaN', df.isnull())
_print('判断是否为NaN', df.isna())
_print('判断是否不为NaN', df['a'].notnull())
df_f_1 = df.fillna(0)
df_f_2 = df.fillna(method='ffill')
_print('原样:', df)
_print('使用前一个填充', df_f_2)
print('-----NaN填充为列平均值-----')
for i in df:
if df[i].isna().any():
df[i].fillna(value=df[i].mean(), inplace=True)
print(df)
df = pd.read_csv('./IMDB-Movie-Data.csv')
_print('df', df)
ascending:指定排序方式,na_position:NaN值放在头还是尾
df.sort_index(inplace=True, ascending=False, na_position='first')
_print('sort_index', df)
by:按照哪个字段排序
df.sort_values(by=['Revenue (Millions)', 'Metascore'], inplace=True, ascending=True, na_position='last')
_print('sort_values', df[['Revenue (Millions)', 'Metascore']].head(20))
_print('info:', df)
df.set_index(keys=['Rank', 'Title'], inplace=True)
_print('使用set_index修改索引列:', df)
df.reset_index(inplace=True)
_print('使用reset_index重置索引列:', df)
left = pd.DataFrame(np.arange(6).reshape(3, 2), columns=['a', 'b'], index=['i1', 'i2', 'i3'])
right = pd.DataFrame(np.arange(4, 10).reshape(3, 2), columns=['c', 'd'], index=['i1', 'i2', 'i23'])
_print('_left', left)
_print('right', right)
将n个datafram进行合并,和SQL的逻辑一模一样
注意:两个Dataframe的字段名不能相同
# inner 内连接,取行索引的交集,不匹配的不展示
inner = left.join(right, how='inner')
_print('inner', inner)
# outer 外连接,取行索引的并集,不匹配的显示NaN
outer = left.join(right, how='outer')
_print('outer', inner)
# left 左连接,使用左边df的行索引,左侧全展示,右侧不匹配的显示NaN
outer_l = left.join(right, how='left')
_print('outer_l', outer_l)
# right 右连接,使用右边df的行索引,右侧全展示,左侧不匹配的显示NaN
outer_r = left.join(right, how='right')
_print('outer_r', outer_r)
left左表,right右表,left_on,right_on两个表的关联字段
merge = pd.merge(left=left, right=right, left_on='b', right_on='d', how='left')
_print('merge', merge)
SQL的聚合函数都可以使用
df = pd.read_csv('./IMDB-Movie-Data.csv')
_print('df', df)
_print('sum', df.sum())
_print('mean', df.mean())
_print('count', df.count())
_print('min', df.min())
_print('max', df.max())
一次性使用多个聚合函数
agg = df.agg(['mean', 'sum', 'max'])
_print('agg', agg)
9.2. agg不同字段不同函数
agg = df.agg({'Rank': ['sum', 'min'], 'Metascore': ['max', 'min']})
_print('agg不同字段不同函数', agg)
df = pd.DataFrame(np.random.randint(1, 10, size=32).reshape(8, 4),
index=pd.date_range('12/1/2020', periods=8),
columns=['A', 'B', 'C', 'D'])
_print('开窗', df)
# 每3个数求一次均值
df['A_rolling'] = df['A'].rolling(window=3).mean()
_print('rolling', df)
expanding 又叫扩展窗口函数,扩展是指由序列的第一个元素开始,逐个向后计算元素的聚合值
# 从1个开始,每次都累加上之前的值
df['A_expanding'] = df['A'].expanding(min_periods=2).sum()
_print('expanding', df)
移动函数,可以获得某列前后n行的值,可以计算同比环比
# 获得A列后面一个的值
df['A_shift+1'] = df['A'].shift(periods=1)
_print('shift', df)
# 获得A列前面一个的值
df['A_shift-1'] = df['A'].shift(periods=-1)
_print('shift', df)
列转行就是把列名提到行里面去
df = pd.DataFrame([['张三', 10, 20], ['李四', 30, 40]], columns=['姓名', '语文', '数学'])
print(df)
需要将不变的列设置为索引(原始字段为姓名,语文,数学,转换后为姓名,科目,成绩。姓名字段不变)
df_stack = df.set_index('姓名').stack()
_print('df_stack', df_stack)
df_stack = df_stack.reset_index() # 重置索引
_print('df_stack重置索引', df_stack)
df_stack.columns = ['姓名', '科目', '成绩']
_print('df_stack,设置列名', df_stack)
id_vars:列转行后,不变的那一列
value_vars:列转行后,需要变动的那些列的列名
var_name:列转为行后,value_vars所属的字段名 http://qn.nulls.cn/202211181539833.png
value_name:列转为行后,新表的值那一列的列明
df_melt = df.melt(id_vars='姓名', value_vars=['语文', '数学'], var_name='科目', value_name='成绩')
_print('df_melt', df_melt)
行转列就是把行里的值提成列名
tmp = pd.DataFrame({'姓名': ['张三', '李四', '王五', '张三', '李四', '王五', '张三', '李四', '王五'],
'科目': ['英语', '英语', '英语', '数学', '数学', '数学', '语文', '语文', '语文'],
'分数': [90, 60, 70, 80, 98, 80, 85, 90, 75]})
_print('行转列原始数据', tmp)
tmp2 = tmp.set_index(['姓名', '科目'])['分数'].unstack().reset_index()
_print('行转列unstack', tmp2)
df = tmp2.rename_axis(columns=None) # 消除科目两个字
_print('行转列unstack', df)
df = tmp.pivot(index='姓名', columns='科目', values='分数').reset_index().rename_axis(columns=None)
print(df)
df = pd.DataFrame([(1, '总裁室', np.NaN),
(2, '研发部', 1),
(3, '市场部', 1),
(4, '后端', 2),
(5, '前端', 2),
(6, '大数据', 2),
(7, '数仓开发', 6),
(8, '数据分析', 6)
],
columns=['ID', 'PRODUCTNAME', 'PARENTID'])
print('*' * 100)
def get_order(argid, df):
# 通过ID获取PARENTID
pid = df.loc[df['ID'] == argid, 'PARENTID']
# print(type(pid), pid) # Series类型
pid = pid.values[0] # 获取PARENTID的具体值
if pd.isna(pid):
return str(argid)
else:
return get_order(pid, df) + '->' + str(argid)
for i in df.values:
df.loc[df['ID'] == i[0], ['ORDERID']] = get_order(i[0], df)
print(df)
data = [{'word': ['a', 'q', 'a']}, {'word': ['qwe', 'qwe', 'a', 'asd']}, {'word': ['sd']}]
lst = []
for dic in data:
lst.extend(dic['word'])
res = pd.Series(lst) # 转Dataframe也行
res = res.value_counts().to_dict()
print(res)
联系客服