一、常用操作
1、数据读取
df = pd.read_csv('data/train.csv' , encoding='utf-8' ,header=None ,names=['timestamp' ,'value' ,'label' ])
df.to_csv('data/data.csv' ,header=None ,index=None )
table = pd.read_table(filename, sep='\t' , chunksize=1000000 )
df_list = []
for df in table:
df_list.apend(df)
df = pd.concat(df_list, ignore_index=True )
读取数据之后,要先对数据有个初步了解,有空值的先处理空值
df.shape
df.dtypes
df.columns
df.head(n)
df.tail(n)
df.info()
df.describe()
df['A' ].nunique()
df['label' ].value_counts()
df.isnull().any ()
df.isnull().T.any ()
获取某一列的统计值
df['A' ].sum ()
df['A' ].max ()
df['A' ].min ()
df['A' ].mean()
df['A' ].std()
df['A' ].median()
查看两列数据是否存在关系,画两者的关系图
matplotlib
import matplotlib.pyplot as plt
plt.plot(df['x' ],df['y' ],'o' )
fig=plt.figure()
axes1=fig.add_subplot(2 ,2 ,1 )
axes2=fig.add_subplot(2 ,2 ,2 )
axes1.plot(df1['x' ],df1['y' ],'o' )
axes2.plot(df2['x' ],df2['y' ],'o' )
axes1.set_title("dataset1" )
axes2.set_title("dataset2" )
fig.suptitle("Title Data" )
fig.tight_layout()
dataframe自带plot
fig,ax = plt.subplots()
ax = tips['total_bill' ].plot.hist()
plot.show()
ax = tips['tip' ].plot.kde()
ax = tips.plot.scatter(x='total_bill' ,y='tip' ,ax=ax)
3、处理NaN值
from numpy import NaN,NAN,nan
df[df["date" ].isnull()]
df.dropna(axis=1 , how='all' ,inplace=True )
df.dropna(subset=['A' ],inplace=True )
df.fillna(value=0 ,inplace=True )
df.fillna({"A" :0 ,"B" :1 })
df.fillna(method='ffill' )
df.fillna(df["score" ].mean(),inplace=True )
df=df.fillna(df.interpolate())
df["value" ] = df.groupby("name" ).transform(lambda x: x.fillna(x.mean()))
4、创建Dataframe
df = pd.DataFrame([['a' ,'b' ,'c' ,'d' ]],columns=['A' ,'B' ,'C' ,'D' ])
df = pd.DataFrame()
data_dict = {'A' :'a' ,'B' :'b' ,'C' :'c' ,'D' :'d' }
df.append(data_dict ,ignore_index=True )
5、包含值而非变量列处理
df = pd.melt(df,id_vars='religion' ,var_name='income' ,value_name='count' )
6、某列分割为多列
df_A = df.A.str .split('_' )
df['status' ] = df_A.str .get(0 )
df['country' ] = df_A.str .get(1 )
7、列名更换
df.rename(columns={"A" : "姓名" , "B" : "年龄" },inplace=True )
8、删除列和行
df.drop(["A" , "B" ], axis=1 , inplace=True )
df.drop(index=del_indexs, axis=0 , inplace=True )
9、筛选数据
df[2 :3 ]
df['20180709' :'20180710' ]
df[df.A > 3 ]
df.loc['20180711' ]
df.loc[:,['B' ,'C' ]]
df.loc[(df['A' ]>1 ) & (df['B' ]=='male' ),:]
df.iloc[-1 ]
df.iloc[1 :3 , 2 :4 ]
df.iloc[[0 , 2 ], 2 :4 ]
df1 = df[df["id" ]=="2301" ]
value = df1.iloc[0 ]["A" ]
df = df.loc[df["remarks" ].str .contains('测试|安装' )]
10、修改数据
df.loc[index, 'B' ] = 1
df.loc[df.A>0 , 'B' ] = 1
df.iloc[2 , 2 ] = 1
df.A[df.A > 3 ] = 1
df.A[df.C == "1" ] = df.B[df.C== "1" ]
11、保留小数和百分数处理
df["A" ] = round (df["A" ], 2 )
df["ratio" ] = df["ratio" ].apply(lambda x: '%.2f%%' % (x * 100 ))
df["ratio" ] = df["ratio" ].apply(lambda x: '{0:.2%}' .format (x))
12、相关值替换
df1["math" ] = df1["math" ].map ({0 :100 })
df1.loc[df1["math" ]==0 ,"math" ] = 100
df.replace(to_replace=0 , value=100 )
13、获得某列去重后的数据
df.drop_duplicates()
df.drop_duplicates(subset = 'A' )
df.drop_duplicates(subset = 'A' ,keep='last' )
14、格式转换
df_list = df.to_dict('records' )
ids = np.array(df["id" ]).tolist()
df['value' ] = df_train['value' ].map (str )
df['value' ] = df_train['value' ].astype('int' )
df['sex' ] = df_train['sex' ].astype('category' )
二、日期数据处理
1、加载日期列数据
df = pd.read_csv('data/train.csv' ,parse_dates=[0 ])
df['year' ] = df['date' ].dt.year
df.index = df['date' ]
2、格式转换
df["date" ] = pd.to_datetime(df["date" ],format ='%Y-%m-%d' )
df['date' ] = df['date' ].apply(lambda x: datetime.strptime(x, '%Y-%m-%d' ))
df["date" ] = df["date" ].apply(lambda x: x.strftime("%Y-%m" ))
3、处理缺失日期的数据
使用一个日期范围为数据集重建索引
head_range = df.date_range(start='2020-01-01' ,end='2020-12-31' )
df.index = df['date' ]
df.reindex(head_range)
4、 按日、周、月统计
df_day = df.resample("2D" , on="date" , label="left" ).sum ()
df_week = df.resample("W" , on="date" , label="left" ).sum ()
df_month = df.resample("MS" , label="left" ,closed="left" ).sum ()
三、合并数据
1、concat
df = pd.concat([df1, df2, df3], join='inner' , axis=1 , ignore_index=True )
df = pd.concat([df1, df2], axis=0 , ignore_index=True )
1、按列合并之后,如果连接方式为"inner",则最终数据条数由少的决定,长度长的数据下边就会丢失;如果连接方式为"outer",则最终数据条数由多的决定,长度短的数据下边由NaN进行填充。
2、按行合并之后,如果连接方式为"inner",则最终数据列数为两个表共同的列,不同的列就会丢失;如果连接方式为"outer",则最终列为两个表所有列并集,缺失的值由NaN进行填充。
3、只保留索引匹配的结果。
2、merge
df = pd.merge(df3, df4, on=['key1' , 'key2' ], how='right' )
df = pd.merge(df3, df4, left_on='key1' , right_on='key2' )
注意问题:
1、有时候merge会出错,主要由于数据中有重复数据,要先去掉重复数据再merge
df.drop_duplicates(subset='game_id' , keep=False , inplace=True )
2、合并之后,最好先删除之前的索引,方便以后的计算
df.reset_index(drop=True , inplace=True )
四、排名与排序
1、排名,生成排序序号列。不改变数据顺序
df["rank" ] = df["A" ].rank(ascending=False , method='min' )
df['A_sort' ]=df['A' ].groupby(df['B' ]).rank(ascending=False ,method='min' )
排名列数据格式为float64。
method有四种类型:"first": 根据值在数组中出现的顺序进行排名 ,
"min": 用整个分组的最小排名 ,"max": 用整个分组的最大排名 ," average ":默认方式,平均排名
2、排序,改变数据顺序
df = df.sort_values(by=["B" ],ascending=[False ])
五、分组和切分
1、分组统计
df_group1 = df1.groupby(by=["class_id" ], as_index=False ).apply(max )
df_group2 = df1.groupby(by=["class_id" ])[["math" ,"english" ]].apply(max ).reset_index()
2、分组求和
df_sum = df.groupby(by=["A" ,"B" ], as_index=False )["math" , "english" , "chinese" ].sum ().reset_index()
3、分组计数
df_count = df.groupby(by=["A" ,"B" ], as_index=False )["id" ].count().reset_index()
4、分组求累加值
df["cumsum" ] = df["A" ].groupby(by=["id" ], as_index=False ).cumsum().reset_index()
注:在分组统计时,如果某列含有空值(“”),会造成对该列分组统计出现问题。
解决方式:再分组统计之前先对空值进行替换。
df.replace("" ,0 ,inplace=True )
groupby分组默认会把分组依据列变成索引,可以用reset_index方法重置或者说取消索引,将它保留在列的位置,维持DataFrame格式,方便后续匹配。
切分常用于一维数组的分类和打标
df["label" ] = pd.cut(x = df['A' ],bins = [0 ,60 ,80 ,90 ,100 ],right = False ,labels = ['不及格' ,'及格' ,'良' ,'优' ])
6、agg
df_mean = df.groupby(by=["A" ,"B" ], as_index=False )["math" ].agg(np.mean)
def my_mean_diff (values,diff_value ):
n = len (values)
sum = 0
for value in values:
sum +=value
mean = sum /n
return mean-diff_value
agg_mean_diff = df.groupby('year' ).lifeExp.agg(my_mean_diff,diff_value=df.lifeExp.mean())
df_dict = df.groupby('year' ).agg({
'lifeExp' :'mean' ,
'pop' :'median' ,
7、transform
def fill_na_mean (x ):
avg = x.mean()
return x.fillna(avg)
df['fill_score' ] = df.groupby('sex' ).score.transform(fill_na_mean)
8、过滤器filter
df_filter = df.groupby('size' ).filter (lambda x:x['size' ].count()>=10 )
1、apply用法
def f (x ):
if x == 'male' :
return '男'
elif x == 'female' :
return '女'
df["sex" ] = df["sex" ].apply(f)
df["sex" ] = df["sex" ].apply(lambda x: '男' if x == 'male' else '女' )
df["sex" ] = df["sex" ].map ({'male' : '男' })
注:map比apply效率要高。简单的替换优先选用map,复杂操作需要使用apply配合编写的规则函数来实现。
2、apply传参
def circle_rate (df,arg1,arg2,arg3 ):
x = df[arg1]
y = df[arg2]
z = df[arg3]
return x - y if y==z else (x-y)/(y-z)
df["day_bef" ] = df.apply(circle_rate, axis=1 , arg1="anzhuang" , arg2="anzhuang_bef" , arg3="anzhuang_bef_bef" )
df["day_bef" ] = df.apply(circle_rate, axis=1 , args=("anzhuang" ,"anzhuang_bef" ,"anzhuang_bef_bef" ))
3、向量化函数
使用numpy
@np.vectorize
def divide (x, y ):
if y == 0 :
return np.NaN
else :
return x / y
df['C' ] = divide(df['A' ], df['B' ])
使用numba
@numba.vectorize
def divide_numba (x, y ):
if int (y) == 0 :
return np.NaN
else :
return x / y
df['C' ] = divide_numba(df['A' ].values, df['B' ].values)
七、其他操作
1、pivot_table和pivot
透视表函数
df_pivot = pd.pivot(df, index="cs" , columns="rate" ).reset_index()
df_pivot_table = pd.pivot_table(df,index=["A" ,"B" ],columns="rate" ,aggfunc="count" ).reset_index()
df_pivot = pd.pivot(df, index="cs" , columns="rate" )
plt.pcolor(df_pivot ,cmap='RdBu' )
plt.colorbar()
plt.show()
pivot与pivot_table区别:
pivot要求行与列的交叉值的索引必须唯一,否则会报错。
pivot_table会将重复索引的值求均值。
2、并行计算
from pandarallel import pandarallel
pandarallel.initialize(nb_workers=2 )
df["B" ] = df["A" ].parallel_apply(func)
注意pandarallel目前只能用在linux和maco,不能用在windows下
八、遇到的坑
1、merge操作时,如果left连接,merge之后有NAN值,该列整数类型会变为浮点类型。inner连接即可解决。或者填充之后,在转换该列数值类型。
2、df1=df与df1=df.copy()都是对df的引用。如果想要一个完全独立的dataframe,一定要用df1=df.copy(deep=True)
769
tigeriaf
Python
pandas
2611
王伟同学44009
Python
NumPy
1940
程序员进化者