pandas Alignment(Boardcasting) 小结
所谓Data alignment,实际就是数据对齐
在pandas-docs中,出现过alignment的地方主要有:
flexible-binary-operations:http://pandas.pydata.org/pandas-docs/version/0.19.2/basics.html?highlight=align#flexible-binary-operations
data-alignment-and-arithmetic:http://pandas.pydata.org/pandas-docs/version/0.19.2/dsintro.html?highlight=align#data-alignment-and-arithmetic
add(), sub(), mul(), div()
实际上最主要的还是Dataframe和Dataframe、Series和Series、或者Dataframe和Series之间进行binary operation(加减乘除时),会涉及到alignment,也即boardcast的规则。
add(), sub(), mul(), div() 对应'+' , '-', '*', '/'。当Dataframe 与 Series 进行操作是,默认对Series是把其index对应到Dataframe的Column上,即broadcasting row-wise(看成行向量,复制成一个矩阵)
但如果Series和Dataframe都以dates相关的index作为index,则是column-wise(看成列向量,复制成一个矩阵)
若要改变默认的alignment方式,则可通过指定传入以上四个函数的 axis 可选的有0(‘index’)和1(‘columns’)
where函数
where()中align的性质可以详参:https://stackoverflow.com/questions/44819339/pandas-dataframe-where-alignment
里面说的非常详细。
where函数同样支持alignment(broadcast)。同样可以传入axis参数指定row(0)或者column(1)
df.where(cond, other=Series, axis)
当dataframe 调用where()且other 传入Series时,
axis=0即指定Series的index与dataframe的column name匹配(即沿着row align,沿着行boardcast)
axis=1即指定Series的index与dataframe的index匹配(即沿着column align,沿着列boardcast)
因此构造Series的时候要注意index!!!可以通过df[colname]来取index 和 df.index相同的column Series,或者通过df[0]来取index和df.name相同的row Series。
若匹配不上,则对应row/column 填入NAN(即默认值)。
df = pd.DataFrame(np.random.randn(8, 4), columns=['A', 'B', 'C', 'D'])
df
s = pd.Series([77,88,99],index=list('ABE')) print('the index of s is {}'.format(s.index.tolist())) s
axis=1,与column name匹配。由于没有df column names 中没有E,因此除了A、B列之外,s的E对应的数据无法起效。
df.where(df>0,s,axis=1) #align with column,i.e. copy s accroding to number of rows and subsitiute into df
s = pd.Series([77,88,99],index=[1,2,4]) print('the index of s is {}'.format(s.index.tolist())) s
同理可以看到只有df中对应的 1 2 4 row 上的数据被替换,其余行上的数据仍是NAN。
df.where(df>0,s,axis=0) #align with row,i.e. copy s accroding to number of columns and subsitiute into df
利用df本身的row 或者 column作为other 传入where():
s = df['A'] print('The index of A column is {} \n'.format(s.index.tolist())) print(s,'\n') df.where(df>0, s, axis=0)
s = df.iloc[1] print('The index of 1 row is {} \n'.format(s.index.tolist())) print(s,'\n') df.where(df>0, s, axis=1)