1 dataframe和series操作

1.1 构造dataframe

1) 空dataframe

通过columns,index参数指定dataframe的行索引、列名。

df1 = pd.DataFrame(columns=['c1', 'c2'], index=['ind1', 'ind2'])

2) 通过字典构造dataframe,并给dataframe添加列;可以通过index=[]参数设置df的索引。

dict_v = {'c1': ['a', 'b', 'c'],

'c2': [1, 2, 3]}

df1 = pd.DataFrame(dict_v)

print(df1.shape[1])

df1['randn_value'] = np.random.normal(0, 1, len(df1))

1.2 取dataframe数据

1) iterrows()

for index_, row in df1.iterrows():

print(index_)

print(row, row.values[0])

iterrows()按行遍历dataframe或series,返回两个元素:行索引和行值,其中行值为Series格式,可以根据list索引取具体的数值。

结果:

2) itertuples()

itertuples为每一行产生一个namedtuple,并且行的索引值作为元组的第一个元素,pandas类型。

for nametuple in df1.itertuples():

print(nametuple)

print(nametuple[0], type(nametuple))

3) dataframe按某列的值取数据

temp_df[temp_df.c1 == 'aa']['c2']

dataframe对象temp_df的c1列值为aa时temp_df的c2列的值;

4) dataframe根据列值取行索引

temp_df[temp_df.c1 == 'aa'].index.to_list()

temp_df的c1列值为aa时,temp_df的行的索引;

5) dataframe 根据行索引和列名修改dataframe的值

final_result.loc[10, 'c1'] = abc

将final_result的10行c1列的值改为abc;

6) dataframe根据列名取值

sorted(list(set(pre_result['c3'].to_list())))

返回list格式,set()去重,list()改回list格式,sorted()排序;

7) 取dataframe的部分列

df_after[['c1', 'c3', 'c6']]

8) dataframe.loc[0]——根据数字型行索引的值取值,

print(retemp.loc[0])

retemp:

asset_return asset_vol

0 1 2

1 11 12

output:

asset_return 1

asset_vol 2

9) dataframe.iloc[1]——根据行顺序取值,取第i行,从0开始

retemp:

asset_return

asset_vol

b a

ee dd

output:

asset_return dd

asset_vol ee

10)根据多个条件过滤数据

tmp = holding.loc[(holding['ACCOUNT'] == '高') & ((holding ['ASSET'] == '企业债') | (holding['ASSET'] == '金融债'))]

取名为holding 的dataframe的ACCOUNT列元素为“高”且ASSET列元素为'企业债'或'金融债'的所有行数据

holding:

ASSET ACCOUNT DV10

0 企业债 高 5.000

1 金融债 高 5.000

2 国债 高 2.109

3 企业债 资本 5.000

4 金融债 资本 5.000

5 国债 资本 2.568

6 企业债 低 5.000

7 金融债 低 5.000

8 国债 低 1.745

output:

ASSET ACCOUNT DV10

0 企业债 高 5.0

1 金融债 高 5.0

1.3 索引

1) 修改列名或索引名

df_after = df_after.rename(columns={base_type: 'values'})

修改列名base_type为’values’。

2) dataframe.set_index('return')——将return列的值作为新的行索引

print(retemp, '\n', retemp.set_index('return'))

output:

return asset_vol

0 a b

1 dd ee

return

asset_vol

b a

ee dd

3) dataframe.reset_index()

重置行索引为数字型索引,参数drop=True时丢失原索引列,参数inplace=True时,修改原df,为false时,返回新的df

output: (drop=False)

index return vol

0 0 a b

1 1 dd ee

output: drop=True

return vol

0 a b

1 dd ee

retemp:

return

vol

b a

ee dd

print(retemp.reset_index(inplace=False))

print(retemp)

output:inplace=False时返回的结果

index return vol

0 0 a b

1 1 dd ee

原retemp没有改变

return vol

0 a b

1 dd ee

1.4 df.drop_duplicates(keep='first', inplace=False)

删除series的重复项

1.5 dataframe的apply方法

1) 使用apply方法对dataframe的列应用某函数

def apply_age(x,bias):

return x+bias

#以元组的方式传入额外的参数

data["age"] = data["age"].apply(apply_age,args=(-3,))

data.head()

修改前:

stature weight smoker gender age color

0 169 82 False 女 64 2

1 189 49 False 男 85 2

2 182 40 False 女 36 2

3 162 51 False 女 77 0

4 156 75 True 女 20 0

修改后:新增加一列'new_age'

stature weight smoker gender age color new_age

0 169 82 False 女 64 2 61

1 189 49 False 男 85 2 82

2 182 40 False 女 36 2 33

3 162 51 False 女 77 0 74

4 156 75 True 女 20 0 17

2) 对多列使用apply函数,并指定沿哪一轴

axis=0,列;axis=1,行。

# 沿着0轴求和

print(data)

res = data[["stature","weight","age"]].apply(np.sum, axis=0)

print(res)

data:

stature weight smoker gender age color new\_age

0 156 43 False 女 20 0 15

1 167 89 True 女 31 1 26

2 161 74 True 男 24 2 19

3 185 63 True 女 68 0 63

4 156 51 False 男 28 1 23

5 166 64 False 男 43 1 38

6 158 53 True 男 37 2 32

7 189 87 True 女 33 1 28

8 182 79 True 男 75 1 70

9 152 84 True 男 35 2 30

output:

stature 1672

weight 687

age 394

1.6 np.asarray(a, dtype=None, order=None)

将输入转化为数组

1.7 dataframe指定的列做运算,列名要一样

res_df['q'] = res_df['q'] / df['q']

res_df和df的q列相除

1.8 判断dataframe的数据是否为NaN

temp_df[temp_df.c1 == cc_]['c2'] is np.NaN

1.9 拼接dataframe,pd.concat()

拼接dataframe,列索引可以不一样,拼接后的结果会保留原df的行索引,当两个df的列数量不一样时,会填充NaN

df = pd.concat([df1, df2])

input:

Q1 Q2

0 asset path

1 asset path

2 asset path

3 asset path

Q1 Q2 Q3

0 quater 0.6641355 0.664235635

1 quater 0.6641355 0.664235635

2 quater 0.6641355 0.664235635

3 quater 0.6641355 0.664235635

4 quater 0.6641355 0.664235635

output:

Q1 Q2 Q3

0 asset path NaN

1 asset path NaN

2 asset path NaN

3 asset path NaN

0 quater 0.6641355 0.664235635

1 quater 0.6641355 0.664235635

2 quater 0.6641355 0.664235635

3 quater 0.6641355 0.664235635

4 quater 0.6641355 0.664235635

1.10 设置打印的数据小数点位数

pd.set_option('precision', 10)

1.11 字典转dataframe,设置数据格式

data1 = {'Q1': ['0.1', '0.2', 0.3],

'Q2': [1, 2, '3']}

df1 = pd.DataFrame(data1, dtype=np.float)

1.12 df.shift(n)

dataframe向下平移n行,n是负数时表示向上平移,n为正数则向下平移。

1.13 操作文件

(一)to_excel()可以选择要保存的sheet

writer = pd.ExcelWriter('df2.xlsx',)

df1.to_excel(writer, index=False, sheet_name='aaa')

(二)to_csv(),mode='a'——设置写入的模式:添加

一次写入

df1.to_csv(path_or_buf=file_name, index=False, mode='a')

分行写入,newline=''——去空行

with open("test0.csv", "a+", newline='') as csvfile:

writer = csv.writer(csvfile, dialect='excel')

# 先写入columns_name

writer.writerow(['Q1', "Q2", "Q3", "Q3"])

for i in range(len(column1)):

# 写入多行用writerows

writer.writerow([column1[i], column2[i], column3[i], column4[i]])

(三)读csv文件为dataframe,header=None:表示csv文件中不包含列名,names=[]:设置df的列名

df_after = pd.read_csv(filepath_or_buffer=file_name, header=None, names=['c1', 'c2', 'c3', 'c4'])

1.14 pivot函数和pivot_table函数

1) pivot函数

对dataframe行列互换,可以接收三个参数,分别是index、columns和values,其中index用来指定转换后DataFrame对象的纵向索引,columns用来指定转换后DataFrame对象的横向索引或者列名,values用来指定转换后DataFrame对象的值。

2)pivot_table函数

import numpy as np

import pandas as pd

df_yield = pd.read_csv('test_file.csv',index_col=0)

df_yield.columns

读取测试文件,可以看到该文件的数据列名如下:

Index(['class', 'path', 'time', '5', '15', '25', '30', '40', '50'], dtype='object')

把列class作为索引,其他列求均值,对不能转换为数字求均值的列,舍弃

df1 = pd.pivot_table(df_yield, index=['class'])

print(df1.columns)

print(df1.tail(10))

此时的列名:

Index(['15', '25', '30', '40', '5', '50', 'path'], dtype='object')

由于列class的元素只有4种,所以按class列求均值之后,数据只剩下4行。效果等价于按class列groupby,然后对group每一列求均值。

15 25 30 40 5 50 path

class

AAA 0.044339 0.046938 0.048070 0.050009 0.034979 0.051728 100.5

AAplus 0.047184 0.049930 0.051079 0.053051 0.037045 0.054804 100.5

Finance 0.040211 0.043424 0.044744 0.045551 0.032856 0.045669 100.5

Government 0.033494 0.035970 0.037322 0.037890 0.026780 0.038292 100.5

把列class、time作为索引,其他列按两层索引求均值。两层索引的层级前后,不影响均值,只是在数据展示上有差异。

df2 = pd.pivot_table(df_yield, index=['class','time'])

print('总行数=', len(df2))

print(df2.tail(12))

可以看到此时结果共有24行,每个class下分为6个季度时间。

总行数= 24

15 25 30 40 5 50 \

class time

Finance Q0 0.039731 0.042170 0.043706 0.044291 0.034036 0.044536

Q1 0.039809 0.042549 0.043996 0.044670 0.033429 0.044872

Q2 0.040048 0.043091 0.044449 0.045209 0.033022 0.045357

Q3 0.040182 0.043549 0.044826 0.045681 0.032468 0.045782

Q4 0.040655 0.044342 0.045535 0.046474 0.032323 0.046505

Q5 0.040841 0.044843 0.045951 0.046981 0.031861 0.046962

Government Q0 0.035327 0.037598 0.039573 0.039782 0.029238 0.040025

Q1 0.034580 0.036939 0.038666 0.039020 0.028201 0.039328

Q2 0.033873 0.036304 0.037779 0.038274 0.027267 0.038643

Q3 0.033093 0.035623 0.036854 0.037499 0.026211 0.037935

Q4 0.032418 0.035007 0.035983 0.036765 0.025372 0.037260

Q5 0.031672 0.034347 0.035076 0.036002 0.024393 0.036562

path

class time

Finance Q0 100.5

Q1 100.5

Q2 100.5

Q3 100.5

Q4 100.5

Q5 100.5

Government Q0 100.5

Q1 100.5

Q2 100.5

Q3 100.5

Q4 100.5

Q5 100.5

以time为索引,class的值为列,求每个value的均值/标注差/方差/最大值/最小值/中位数等,可以通过为aggfunc参数对每列指定所求的数据类型

df3 = pd.pivot_table(df_yield, index=['time'], columns=['class'], values=[ '15','5','50'], aggfunc={'15':[np.mean, np.sum], '5':[np.max, np.min]})

print('总行数=',len(df3))

print(df3.tail(12))

总行数= 6

15 \

mean sum

class AAA AAplus Finance Government AAA AAplus Finance

time

Q0 0.045187 0.049781 0.039731 0.035327 9.037400 9.956200 7.946200

Q1 0.044888 0.048782 0.039809 0.034580 8.977634 9.756364 7.961770

Q2 0.044535 0.047730 0.040048 0.033873 8.907071 9.545923 8.009544

Q3 0.044197 0.046693 0.040182 0.033093 8.839475 9.338513 8.036317

Q4 0.043844 0.045641 0.040655 0.032418 8.768860 9.128262 8.130974

Q5 0.043383 0.044480 0.040841 0.031672 8.676511 8.896098 8.168294

5 \

amax amin

class Government AAA AAplus Finance Government AAA AAplus

time

Q0 7.065400 0.037301 0.040330 0.034036 0.029238 0.037301 0.040330

Q1 6.915979 0.041402 0.044089 0.045218 0.035434 0.033998 0.036591

Q2 6.774569 0.048506 0.050857 0.053692 0.040057 0.031677 0.033882

Q3 6.618624 0.047758 0.049734 0.055650 0.038836 0.029085 0.030924

Q4 6.483629 0.057912 0.059542 0.070206 0.046191 0.026386 0.027870

Q5 6.334477 0.060461 0.061719 0.073710 0.045853 0.023986 0.024998

class Finance Government

time

Q0 0.034036 0.029238

Q1 0.024415 0.023414

Q2 0.022143 0.021536

Q3 0.021386 0.020361

Q4 0.020833 0.018927

Q5 0.017635 0.016940

1.15 pd.merge()函数

merge(left, right, how='inner', on=None, left_on=None, right_on=None,

left_index=False, right_index=False, sort=False,

suffixes=('_x', '_y'), copy=True, indicator=False,

validate=None)

作用:拼接两个dataframe对象,可以通过参数left,right,on,how,sort等参数设置多种拼接方式。

left/right:设置待拼接dataframe的左右顺序;

on:设置拼接dataframe的连接键,必须是待拼接的两个dataframe中同时存在的,可以是一个列表,表示同时按多列拼接;

left_on=/ right_on=:分别设置待拼接的两个dataframe的连接键,可以不同;

how:设置拼接方式,'left', 'right', 'outer', 'inner'。

sort: 按字典顺序通过连接键对结果DataFrame进行排序。

1.16 pd.align()函数

按内连接或外连接对两个dataframe做过滤。

align(self, other, join='outer', axis=None, level=None, copy=True, fill_value=None, method=None, limit=None, fill_axis=0, broadcast_axis=None)

1.17 drop()函数

inplace=True表示修改之后,覆盖原dataframe。

按索引删除行:

view_data.drop(index=['r1', 'r2'], inplace=True)

按列名删除列:

view_data.drop(columns=['c1', 'c2'], inplace=True)

根据行数据删除数据:

先过滤出tdate列等于dd的行,再获取这些行的索引,最后根据索引删除行数据。

df.drop(df[df.tdate == dd].index, inplace=True)

1.18 dropna()函数

按行删除nan值,参数how=’all’,表示一行全部元素都是nan时才删除;参数how=’any’,表示一行中有nan就删除。

view_data.dropna(axis=0, how='all', inplace=True)

按列删除nan值:

view_data.dropna(axis=1, how='all', inplace=True)

dropna()函数只能删除np.nan,不能删除空字符串。

dict3={'col1':['','4.5 ',' 6 .2 '],'ind':[0,1,2]}

df3=pd.DataFrame(dict3,index=range(3))

tmp_df = df3.copy()

print('原始DF:\n',tmp_df)

tmp_df.set_index('ind', inplace=True)

tmp_df.dropna(axis=0, how='all', inplace=True)

print('删除nan之后的DF:\n',tmp_df)

由输出结果可以看到,col1列为空字符串的行并没有被删除点。此时,我们需要先用replace函数先把空字符串替换为np.nan,然后再使用dropna函数。

原始DF:

col1 ind

0 0

1 4.5 1

2 6 .2 2

删除nan之后的DF:

col1

ind

0

1 4.5

2 6 .2

1.19 给dataframe赋值

1) 修改已经存在的列的元素

# 法1

final_df.at[co, 'mvp'] = PreDeter['mvp']

# 法2

df1.loc[0.1]['Q2'] = 0.0001

df1.loc[0.2]['Q2'] = 0.0002

2) 新增列并对所有行赋值

at函数的参数可以是series,loc函数的参数不可以是series。

给set_2列的所有行赋值,如果不存在该列则会创建。

# 法一

price_df.at[:,'set_2'] = ['CBondAAA', 'CBondAA', 'FoBond']

# 法二

price_df.loc[:,'set_2'] = ['CB', 'CBAA', 'FB']

# 法三:列Q4为新加的列,列数据为[0.41, 0.42, 0.43],这种方法程序可能会报warning。

df1['Q4'] = [0.41, 0.42, 0.43]

Q2 Q4

Q1

0.1 5.0 0.41

0.2 6.0 0.42

0.3 8.0 0.43

3) 修改指定行的列数据

修改行索引为3的所有列的数据,当有多行的索引为3时,同时修改。

price_df.loc[3,:] = [2, 'Q2', 2.001, 0.0059, 2.103, 'stock', '']

1.20 给dataframe新加一列

列Q4为新加的列,列数据为[0.41, 0.42, 0.43]

df1['Q4'] = [0.41, 0.42, 0.43]

output:

Q2 Q4

Q1

0.1 5.0 0.41

0.2 6.0 0.42

0.3 8.0 0.43

1.21 pd.to_numeric

将dataframe多列的数据格式改成float。

final_df[['0', '0.5', '1']] = final_df[['0', '0.5', '1']].apply(pd.to_numeric)

1.22 dt.date

将dataframe列的数据格式改成日期

final_df['date'] = final_df['date'].dt.date

1.23 columns.astype

修改dataframe列名的格式为字符串

final_df.columns = final_df.columns.astype(str)

1.24 series转dataframe

将pandas的series格式数据转换为DF,并转置

tmp_df = row.to_frame().T

1.25 对dataframe按某些列排序

bond_data_df.sort_values(by=['qu', 'pa'])

1.26 pd.tail(n)函数

取dataframe的最后n行数据

res_df_tail = res_df.tail(2)

print(res_df)

print("____________")

print(res_df_tail)

Outut:

A B C

0 A0 B0 C0

1 A1 B1 C1

2 A2 B2 C2

3 A3 B3 C3

0 A4 B4 C4

1 A5 B5 C5

2 A6 B6 C6

3 A7 B7 C7

0 A8 B8 C8

1 A9 B9 C9

2 A10 B10 C10

3 A11 B11 C11

____________

A B C

2 A10 B10 C10

3 A11 B11 C11

1.27 map()函数

print(data)

data['color'] = data['color'].map({'white':0, 'black':1, 'yellow':2})

print(data.head())

data

修改前:

height weight smoker gender age color

0 157 40 True 女 28 white

1 176 76 False 女 37 yellow

2 183 68 False 男 88 yellow

3 160 59 False 男 18 white

4 155 40 True 男 58 black

修改后:

height weight smoker gender age color

0 157 40 True 女 28 0

1 176 76 False 女 37 2

2 183 68 False 男 88 2

3 160 59 False 男 18 0

4 155 40 True 男 58 1

1.28 applymap()

applymap会对DataFrame中的每个单元格执行指定函数的操作

df=pd.DataFrame(

{

"A":np.random.randint(0, 8, 5),

"B":np.random.randint(0, 8, 5),

"C":np.random.randint(0, 8, 5),

"D":np.random.randint(0, 8, 5),

"E":np.random.randint(0, 8, 5),

})

print(df)

df_2=df.applymap(lambda x:np.power(x,0.5))

print(df_2)

修改前:

A B C D E

0 6 7 5 7 3

1 2 7 2 0 4

2 7 5 6 7 5

3 6 3 5 0 4

4 1 4 6 7 4

修改后:

A B C D E

0 2.449490 2.645751 2.236068 2.645751 1.732051

1 1.414214 2.645751 1.414214 0.000000 2.000000

2 2.645751 2.236068 2.449490 2.645751 2.236068

3 2.449490 1.732051 2.236068 0.000000 2.000000

4 1.000000 2.000000 2.449490 2.645751 2.000000

1.29 df.rolling(n)

rolling(self, window, min_periods=None, center=False,

win_type=None, on=None, axis=0, closed=None)

时间窗函数rolling()用于对数据进行平移计算,如计算相邻10个数据的均值mean()、和sum()、方差var()等。

import pandas as pd

data_1 = [[0.1, 0.2, 0.3, 0.4],

[1, 2, 3, 4],

[10, 20, 30, 40],

[0.01, 0.02, 0.03, 0.04]]

res_tmp = pd.DataFrame(data=data_1, columns=['value1', 'value2', 'value3', 'value4'])

res_tmp1 = res_tmp.rolling(2, axis=0).mean()

res_tmp2 = res_tmp.rolling(2, axis=1).mean()

res_tmp3 = res_tmp.rolling(2, axis=1).sum()

res_tmp4 = res_tmp.rolling(2, axis=0).std(ddof=0)

print('---------原始数据----------')

print(res_tmp)

print('---------分割线,列相邻2个数据的均值----------')

print(res_tmp1)

print('---------分割线,行相邻2个数据的均值----------')

print(res_tmp2)

print('---------分割线,行相邻2个数据的和----------')

print(res_tmp3)

print('---------分割线,列相邻2个数据的总体标准差----------')

print(res_tmp4)

output:

---------原始数据----------

value1 value2 value3 value4

0 0.10 0.20 0.30 0.40

1 1.00 2.00 3.00 4.00

2 10.00 20.00 30.00 40.00

3 0.01 0.02 0.03 0.04

---------分割线,列相邻2个数据的均值----------

value1 value2 value3 value4

0 NaN NaN NaN NaN

1 0.550 1.10 1.650 2.20

2 5.500 11.00 16.500 22.00

3 5.005 10.01 15.015 20.02

---------分割线,行相邻2个数据的均值----------

value1 value2 value3 value4

0 NaN 0.150 0.250 0.350

1 NaN 1.500 2.500 3.500

2 NaN 15.000 25.000 35.000

3 NaN 0.015 0.025 0.035

---------分割线,行相邻2个数据的和----------

value1 value2 value3 value4

0 NaN 0.30 0.50 0.70

1 NaN 3.00 5.00 7.00

2 NaN 30.00 50.00 70.00

3 NaN 0.03 0.05 0.07

---------分割线,列相邻2个数据的总体标准差----------

value1 value2 value3 value4

0 NaN NaN NaN NaN

1 0.450 0.90 1.350 1.80

2 4.500 9.00 13.500 18.00

3 4.995 9.99 14.985 19.98

1.30 列转行索引并根据行索引过滤数据

import pandas as pd

map_dict = {0: 'A0', 1: 'A1'}

df1 = pd.DataFrame({'A': [0, 1, 0, 3, 2],

'B': ['B0', 'B1', 'B2', 'B3', 'bb'],

'C': ['C0', 'C1', 'C2', 'C3', 'cc'],

'D': ['D0', 'D1', 'D2', 'D3', 'dd']})

df2 = df1.set_index('A', drop=True)

print("设置A列为行索引:", '\n', df2)

df3 = df2.loc[[0,1]]

print("取行索引为0、1的数据:", '\n', df3)

df4 = df3.rename(map_dict,axis='index').reset_index(drop=False)

print("行索引重命名并重设置索引:", '\n', df4)

设置A列为行索引:

B C D

A

0 B0 C0 D0

1 B1 C1 D1

0 B2 C2 D2

3 B3 C3 D3

2 bb cc dd

取行索引为0、1的数据:

B C D

A

0 B0 C0 D0

0 B2 C2 D2

1 B1 C1 D1

行索引重命名并重设置索引:

A B C D

0 A0 B0 C0 D0

1 A0 B2 C2 D2

2 A1 B1 C1 D1

1.31 dataframe.str.split()

将dataframe的某些列根据分隔符分成多列。

如:将df2的rate_type按照“|”分割成两列,两列的列名分别为'asset_name', 'rate_type'。

df2[['asset_name', 'rate_type']] = df2['rate_type'].str.split('|', expand=True)

input:

year value_type rate

0 2020 asset1|cii 0.19

1 2020 asset1|nii 0.10

2 2020 asset2|cii 0.20

3 2020 asset2|nii 0.29

参数expand=True时,表示将拆分的数据分成多列。

output:

year value_type rate asset

0 2020 cii 0.19 asset1

1 2020 nii 0.10 asset1

2 2020 cii 0.20 asset2

3 2020 nii 0.29 asset2

如果拆分出来的数据的列数多于待存放数据的列,那么将数据从左到右依次保存,直到可存放数据的列用完,多于的数据将被舍弃。

比如:

df2['value_type'] = df2['value_type'].str.split('|', expand=True)

output:

year value_type rate

0 2020 asset1 0.19

1 2020 asset1 0.10

2 2020 asset2 0.20

3 2020 asset2 0.29

参数expand=False时,表示不将拆分的数据分成多列,以list格式保存为一列:

output:

year value_type rate

0 2020 [asset1, cii] 0.19

1 2020 [asset1, nii] 0.10

2 2020 [asset2, cii] 0.20

3 2020 [asset2, nii] 0.29

1.32 pd.isnull()

判断dataframe的元素是否为nan。示例为根据rate列的值判断是否用相同行rate列替换ret列的值,当rate列值为nan时,不替换。

import pandas as pd

real_constrains = dict(

name=['a', 'b', 'c', 'd'],

ret=[0,0.12,0.13, 0.21]

)

constrains = dict(

name=['a', 'b', 'c'],

rate=[0.1, 0.2, 0.0]

)

constrains_df = pd.DataFrame(constrains)

real_constrains_df = pd.DataFrame(real_constrains)

constrains_df = pd.merge(real_constrains_df, constrains_df, on='name', how='left')

print(constrains_df)

constrains_df['ret'] = constrains_df.apply(lambda x: x['ret'] if pd.isnull(x['rate']) else x['rate'],axis=1)

print(constrains_df)

output:

原值:

name ret rate

0 a 0.00 0.1

1 b 0.12 0.2

2 c 0.13 0.0

3 d 0.21 NaN

替换后:

name ret rate

0 a 0.10 0.1

1 b 0.20 0.2

2 c 0.00 0.0

3 d 0.21 NaN

1.33 DataFrame.replace()

replace(self, to_replace=None, value=None, inplace=False, limit=None,

regex=False, method='pad')

to_replace:表示需要被替换的值;

value:表示期望替换进dataframe的值;

inplace:表示是否替换原dataframe中的数据,True表示替换,False时会返回新的dataframe;

limit:表示向前或向后填充的距离。

regex:表示是否将to_replace、value解释为正则表达式。 如果为True,则to_replace必须为字符串。

import numpy as np

import pandas as pd

df1=pd.DataFrame({'col1':['','0.5','1.2'],'ind':[0,1,2]},index=range(3))

df2=pd.DataFrame({'col2':['1.5','0.8'],'ind':[0,1]},index=range(2))

df = df1.merge(df2,on=['ind'],how='left')

print('replace前:\n', df)

replace前:

col1 ind col2

0 0 1.5

1 0.5 1 0.8

2 1.2 2 NaN

1) 替换dataframe中的正负无穷值

df.replace([np.nan, np.inf, -np.inf], 0, inplace=True)

print('replace后:\n', df)

replace后:

col1 ind col2

0 0 1.5

1 0.5 1 0.8

2 1.2 2 0

2) 替换dataframe中的空格

dict3={'col1':['','4.5 ',' 6 .2 '],'ind':[0,1,2]}

df3=pd.DataFrame(dict3,index=range(3))

tmp_df = df3.copy()

print('原始DF:\n',tmp_df)

原始DF:

col1 ind

0 0

1 4.5 1

2 6 .2 2

可以看到,col1列第一行的数据为空字符串,第三行为字符6和小数点之间有空格。

当dataframe的数据中有空字符串或字符串中间有空格时,我们不能使用astype()方法将其格式转换为float形式,所以,需要先把空格去掉,然后把空字符串转换为np.nan。

# 先把空格替换会空字符串

tmp_df['col1']=tmp_df['col1'].str.replace(' ', '')

# 使用正则替换空字符串,astype()方法转换字符串格式时会自动去掉字符串前后的空格。

tmp_df['col1']=tmp_df['col1'].replace(to_replace=r'^\s*$',value=np.nan,regex=True).astype('float')

print('替换后的DF:\n',tmp_df)

# 字符串格式无法与整数100相除

tmp_df['col1']=tmp_df['col1']/100

tmp_df.set_index('ind', inplace=True)

# 按行删除nan值

tmp_df.dropna(axis=0, how='all', inplace=True)

print('替换后的DF用于计算:\n',tmp_df)

替换后的DF:

col1 ind

0 NaN 0

1 4.5 1

2 6.2 2

将col1列的数据格式转换为float之后,可以进行加减乘除运算。

由于dataframe的dropna方法不能删除空字符串,只能删除np.nan,所以也需要进行空字符串replace。

替换后的DF用于计算:

col1

ind

1 0.045

2 0.062

3) 不使用正则替换空格

不使用正则替换空格或空字符串时,只能替换固定的数据格式,比如:下面的替换语句只能将不含空格的空字符串替换为np.nan。

tmp_df['col1']=tmp_df['col1'].replace('', np.nan)

1.34 DataFrame.assign()

df.assign(),为dataframe添加新列或者覆盖原有列。关键字参数为列名,如果列存在,则根据参数更新列值;如果列不存在,则添加新列。

import pandas as pd

import numpy as np

df = pd.DataFrame({'temp_c': [17.0, 25.0]},index=['Portland', 'Berkeley'])

print("原df: \n",df)

df = df.assign(temp_f=lambda x: x.temp_c * 9 / 5 + 32)

print("添加新列到df: \n",df)

df = df.assign(temp_f=df['temp_c'] * 1.5 + 32)

print("修改上一步添加的列值: \n",df)

原df:

temp_c

Portland 17.0

Berkeley 25.0

添加新列到df:

temp_c temp_f

Portland 17.0 62.6

Berkeley 25.0 77.0

修改上一步添加的列值:

temp_c temp_f

Portland 17.0 57.5

Berkeley 25.0 69.5

1.35 df.cumprod()

按指定轴计算dataframe的累乘。

1)使用df.cumprod()和np.pord()

real_constrains = dict(

ret=[0.3,0.12,0.13, 0.21, 6,0.01],

duration = [0.1,1,6,2,5,10]

)

df = pd.DataFrame(real_constrains)

print('原DF:\n', df)

df['cumu_price'] = np.nan

df['temp_cumu_price'] = np.nan

df['cumu_price2'] = np.nan

df['temp_cumu_price'] = df.apply(lambda x: x['duration'] + 1, axis=1)

df['cumu_price2'] = df['temp_cumu_price'].cumprod(axis=0)

print('加1并累乘后的DF: \n', df)

结果如下,对duration列,每个值加1,然后对加1后的列值求累乘。

原DF:

ret duration

0 0.30 0.1

1 0.12 1.0

2 0.13 6.0

3 0.21 2.0

4 6.00 5.0

5 0.01 10.0

加1并累乘后的DF:

ret duration temp_cumu_price cumu_price2

0 0.30 0.1 1.1 1.1

1 0.12 1.0 2.0 2.2

2 0.13 6.0 7.0 15.4

3 0.21 2.0 3.0 46.2

4 6.00 5.0 6.0 277.2

5 0.01 10.0 11.0 3049.2

使用np.pord()函数同样可以实现,但是需要做循环计算,计算速度会比df.cumprod()慢很多。

real_constrains = dict(

ret=[0.3,0.12,0.13, 0.21, 6,0.01],

duration = [0.1,1,6,2,5,10]

)

df = pd.DataFrame(real_constrains)

print('原DF:\n', df)

df['cumu_price'] = np.nan

for idx in range(0, len(df)):

df['cumu_price'][idx] = np.prod(df['duration'][0:idx + 1] + 1)

print('加1并累乘后的DF: \n', df)

可以看到,cumu_price列与cumu_price2列完全一致。

加1并累乘后的DF:

ret duration cumu_price

0 0.30 0.1 1.1

1 0.12 1.0 2.2

2 0.13 6.0 15.4

3 0.21 2.0 46.2

4 6.00 5.0 277.2

5 0.01 10.0 3049.2

2)耗时比较

import time

import random

real_constrains = dict(

ret=np.random.normal(1.151, 0.05, 1000),

duration = np.random.normal(5, 1, 1000)

)

df = pd.DataFrame(real_constrains)

df['cumu_price'] = np.nan

df['temp_cumu_price'] = np.nan

df['cumu_price2'] = np.nan

st_prod = time.time()

for idx in range(0, len(df)):

df['cumu_price'][idx] = np.prod(df['duration'][0:idx + 1] + 1)

et_prod = time.time()

print('all time of prod =', et_prod-st_prod)

st_cumprod = time.time()

df['temp_cumu_price'] = df.apply(lambda x: x['duration'] + 1, axis=1)

df['cumu_price2'] = df['temp_cumu_price'].cumprod(axis=0)

et_cumprod = time.time()

print('all time of cumprod =', et_cumprod-st_cumprod)

可以看到,np.pord()函数计算耗时比df.cumprod()函数长很多。

all time of prod = 0.40705156326293945

all time of cumprod = 0.013093709945678711

1.36 dataframe的sum与cumsum

sum表示按指定轴、指定列求和,只对相同条件中的最后一行赋值;cumsum表示按指定轴、指定列求累加和。

import copy

real_constrains = dict(

duration = [1,1,6,2,5,10],

ret=[0.12,0.12,0.13, 0.21, 6,0.01]

)

df = pd.DataFrame(real_constrains)

print('原DF: \n',df)

df1 = df.copy()

df1['sum_ret'] = df1.groupby(['duration']).sum()

print('求sum后:\n', df1)

df['cum_ret'] = df.groupby(['duration'])['ret'].cumsum()

print('求cumsum后:\n', df)

output:

原DF:

duration ret

0 1 0.12

1 1 0.12

2 6 0.13

3 2 0.21

4 5 6.00

5 10 0.01

求sum后:

duration ret sum_ret

0 1 0.12 NaN

1 1 0.12 0.24

2 6 0.13 0.21

3 2 0.21 NaN

4 5 6.00 NaN

5 10 0.01 6.00

求cumsum后:

duration ret cum_ret

0 1 0.12 0.12

1 1 0.12 0.24

2 6 0.13 0.13

3 2 0.21 0.21

4 5 6.00 6.00

5 10 0.01 0.01

1.37 。。。

2 Pandas聚合和分组

2.1 GroupBy

1) 使用groupby对dataframe按照列名、索引分组

然后对分组的数据求均值、方差等计算。

Grouped = df.groupby[‘column_name’]

变量grouped是一个GroupBy对象,它实际上还没有进行任何计算

同时传入多个对象:对df按照column_2和column_3两级分组,然后求列column_1的均值。

Grouped = df[‘column_1’].groupby([df[‘column_2’],df[‘column_3’]]).mean()

使用size()方法查看每个分组的数据大小。

2) GroupBy对象支持迭代

产生一组二元元组(由分组名和数据块组成),其中数据块的索引与原dataframe一致。

for name_, group_df in df_res.groupby('path'):

print(name _)

print(group_df)

对于多重键的情况,元组的第一个元素将会是由键值组成的元组:

for (k1, k2), group_df in df.groupby(['key1', 'key2']):

print(k1, k2)

print(group_df)

3) groupby默认是在axis=0上进行分组的,通过设置也可以在其他任何轴上进行分组

grouped = df.groupby(df.dtypes, axis=1)

4) 分组信息可以是字典

a b c d e

1 0.306336 -0.139431 0.210028 -1.489001 -0.172998

2 0.998335 0.494229 0.337624 -1.222726 -0.402655

3 1.415329 0.450839 -1.052199 0.731721 0.317225

mapping

{'a': 'group1', 'c': 'group2', 'b': 'group1', 'e': 'group1', 'd': 'group2', 'f': 'group3'}

将dataframe的列通过字典的键值对映射,可以将多列映射到同一个键值,然后传入字典根据键值分组。

by_column = df1.groupby(mapping, axis=1)

by_column.sum()

group2 group1

1 -1.278973 -0.006092

2 -0.885102 1.089908

3 0.731721 1.732554

5) groupby()的聚合操作

对datafram数据groupby之后,可以对其他单列或多列进行聚合操作,求均值(mean())、最小值(min())、最大值(max())、求和(sum())、中位数(median())、方差(var(ddof=0), var(ddof=1))、标准差(std(ddof=0), std(ddof=1))等。格式有多种。

import pandas as pd

real_constrains = dict(

name=['a', 'b', 'c', 'd', 'a','c'],

ret=[0.3,0.12,0.13, 0.21, 6,0.01],

duration = [0.5,1,6,2,5,10]

)

constrains_df = pd.DataFrame(real_constrains)

print(constrains_df)

res1 = constrains_df.groupby('name')['ret'].std(ddof=0)

# 要对多列求不同的聚合计算时,可以通过agg函数传字典参数进行计算

res2 = constrains_df.groupby('name').agg({'ret':'max','duration':'min'})

res3 = constrains_df.groupby('name')[['ret','duration']].min()

res4 = constrains_df.groupby('name').std(ddof=0)['ret']

6) groupby的transform操作

使用agg操作会将groupby条件相同的数据整合,而transform操作可以将结果返回原dataframe的新列,并将结果返回给每一行。

import pandas as pd

real_constrains = dict(

name=['a', 'b', 'c', 'd', 'a','c'],

ret=[0.3,0.12,0.13, 0.21, 6,0.01],

duration = [0.5,1,6,2,5,10]

)

constrains_df = pd.DataFrame(real_constrains)

print(constrains_df)

res4 = constrains_df.groupby('name')['ret'].mean()

print('初始DF:\n', constrains_df)

[['ret','duration']].min()

# 求均值返回结果将groupby条件相同的行合并

res4 = constrains_df.groupby('name')['ret'].mean()

print('res4结果:\n', res4)

# 使用agg无法将计算结果返回给原DF新的列

constrains_df['ave_ret_agg'] = constrains_df.groupby('name')['ret'].mean()

print('使用agg结果:\n', constrains_df)

# 使用transform可以将计算结果返回原DF的每一行

constrains_df['ave_ret_tra'] = constrains_df.groupby('name')['ret'].transform('mean')

print('使用transform结果:\n', constrains_df)

output:

初始DF:

name ret duration

0 a 0.30 0.5

1 b 0.12 1.0

2 c 0.13 6.0

3 d 0.21 2.0

4 a 6.00 5.0

5 c 0.01 10.0

res4结果:

name

a 3.15

b 0.12

c 0.07

d 0.21

Name: ret, dtype: float64

使用agg结果:

name ret duration ave_ret_agg

0 a 0.30 0.5 NaN

1 b 0.12 1.0 NaN

2 c 0.13 6.0 NaN

3 d 0.21 2.0 NaN

4 a 6.00 5.0 NaN

5 c 0.01 10.0 NaN

使用transform结果:

name ret duration ave_ret_agg ave_ret_tra

0 a 0.30 0.5 NaN 3.15

1 b 0.12 1.0 NaN 0.12

2 c 0.13 6.0 NaN 0.07

3 d 0.21 2.0 NaN 0.21

4 a 6.00 5.0 NaN 3.15

5 c 0.01 10.0 NaN 0.07

2.2 dataframe.str.split()

将dataframe的某些列根据分隔符分成多列。

如:将df2的rate_type按照“|”分割成两列,两列的列名分别为'asset_name', 'rate_type'。

df2[['asset_name', 'rate_type']] = df2['rate_type'].str.split('|', expand=True)

year value_type rate

0 2020 asset1|cii 0.19

1 2020 asset1|nii 0.10

2 2020 asset2|cii 0.20

3 2020 asset2|nii 0.29

参数expand=True时,表示将拆分的数据分成多列。

year value_type rate asset

0 2020 cii 0.19 asset1

1 2020 nii 0.10 asset1

2 2020 cii 0.20 asset2

3 2020 nii 0.29 asset2

如果拆分出来的数据的列数多于待存放数据的列,那么将数据从左到右依次保存,直到可存放数据的列用完,多于的数据将被舍弃。

比如:

df2['value_type'] = df2['value_type'].str.split('|', expand=True)

year value_type rate

0 2020 asset1 0.19

1 2020 asset1 0.10

2 2020 asset2 0.20

3 2020 asset2 0.29

参数expand=False时,表示不将拆分的数据分成多列,以list格式保存为一列:

year value_type rate

0 2020 [asset1, cii] 0.19

1 2020 [asset1, nii] 0.10

2 2020 [asset2, cii] 0.20

3 2020 [asset2, nii] 0.29

2.3 ...

pandas将df赋值到另一个df_pandas基础相关推荐

  1. pandas将df赋值到另一个df_Python pandas将多级列标题df映射到另一个df

    更新应该工作.尝试这个: df1 = df1.set_index('SubscriberKey') df1 Output: Inst A1 A2 A3 A4 SubscriberKey 'abc' 1 ...

  2. pandas将df赋值到另一个df_Python/Pandas:如果匹配的話,將一個df的值添加到另一個df的行的末尾...

    示例代碼 df1 = pd.DataFrame( { 'terms' : ['term1','term2'], 'code1': ['1234x', '4321y'], 'code2': ['2345 ...

  3. pandas任取dataframe中的一个或者多个数据行(head、tail、loc、iloc),将抽取到的一个或者多个数据行复制N次形成新的dataframe

    pandas任取dataframe中的一个或者多个数据行(head.tail.loc.iloc),将抽取到的一个或者多个数据行复制N次形成新的dataframe 目录

  4. MySQL 实现一个字段赋值给另一个字段

    MySQL 实现一个字段赋值给另一个字段 1.将同一个表中的一个字段的值复制给另一个字段UPDATE t_user SET signed_time = create_time 122.将同一个表中两个 ...

  5. python(numpy,pandas8)——pandas大范围赋值和增加特定数据,处理丢失数据(nan)

    文章目录 前言 pandas大范围赋值 增加空数据 处理丢失数据(nan) isnull:查看哪个数据是nan dropna:直接丢掉 fillna:赋值为0 前言 根据 莫烦Python的教程 总结 ...

  6. image1载入大图片时如果stretch=true,image1会显示出大图片的缩图,那么如何将这个缩图镜像复制一份赋值给另一个image2的picture呢?...

    image1载入大图片时如果stretch=true,image1会显示出大图片的缩图,那么如何将这个缩图镜像复制一份赋值给另一个image2的picture呢? Delphi / Windows S ...

  7. 如何将一个vector内容赋值给另一个vector C/C++

    在c/c++中,将一个vector内容赋值给另一个vector的方法大概有如下四个: 方法1: vector<int > v1(v2);//声明 方法2:使用函数assign进行赋值: v ...

  8. vue中,获取一个div的高赋值给另一个div (自适应)

    vue中,获取一个div的高赋值给另一个div (自适应) 问题描述: 左侧是video 为了让video不出现黑边 video是16:9的(怎么写成16:9的盒子 下次说), 左侧的高度会随着页面宽 ...

  9. 将一个实体类赋值给另一个实体类

    1. 自己写工具类 下面这个类便可以帮我们实现. 在Main方法中我给AppointmentOrderParam类初始化并赋值,然后想把这个类的值能够自动赋值给另一个类AppointmentOrder ...

  10. python中将一个列表赋值给另一个列表

    在写杨辉三角时,希望将一个列表直接赋值给另一个列表,就尝试写了一下. list1 = ['1', '2', '3'] list2 = list1 print(list1) print(list2) 运 ...

最新文章

  1. Sphinx编译docs文档
  2. oracle 合并函数
  3. vue data属性中的值绑定到dom上的一些问题
  4. ElasticSearch架构反向思路
  5. 小程序中添加客服按钮contact-button
  6. 小用lambda表达式,查询数组里大于80的个数
  7. paddle2.0实现DNN(minst数据集)
  8. 数学建模系列-优化模型---(一)规划模型
  9. Linux ANSYS FLUENT 在集群上的安装与配置
  10. 谷歌浏览器好用的插件推荐
  11. 2022-2028年中国商用车产业园区行业市场竞争态势及未来前景分析报告
  12. 卫星影像,区划矢量,DEM....教你如何将各种遥感数据收入囊中
  13. 大数据时代:数据收集比数据挖掘更有意义
  14. 设计模式之简单化_Mediator中介者模式_只有一个仲裁者
  15. 在firefox中 屏蔽CSDN博客广告 + 添加百度搜索引擎
  16. pmp中ram和raci的区别_信息系统项目管理师和PMP考试考哪个?
  17. Java-命令行版中国象棋
  18. vue之router莫名其妙的bug
  19. ABAP 资产类BAPI过账 BAPI_ACC_DOCUMENT_POST
  20. cmd打开html文件,网页运行exe,exe软件打开弹出cmd

热门文章

  1. git出现绿色、红色状态的deleted
  2. 【02】Java进阶:17-单例设计模式、多例设计模式、枚举、工厂设计模式、Lombok
  3. [lua]紫猫lua教程-命令宝典-L1-03-01. 闭包
  4. 熟练掌握计算机应用,计算机应用技术专业个人技能怎么写
  5. c# 调用有道智云翻译接口+语音组件tts
  6. R实战之从头到尾分析广告数据集
  7. 打造自己的win10精简系统
  8. IPV4内网地址网段
  9. 手机android的文件怎么恢复,手机文件误删除怎么恢复-互盾安卓恢复大师
  10. Spring Boot获取节假日API