如何根据pandas数据帧中的行条件添加新列?

时间:2017-05-03 06:03:06

标签: python pandas dataframe

我想基于行条件添加新列,该行基于同一数据帧的两个不同列。

我的 Dataframe -

df1_data = {'e_id': {0:'101',1:'',2:'103',3:'',4:'105',5:'',6:''},
        'r_id': {0:'',1:'502',2:'',3:'504',4:'',5:'506',6:''}}
df=pd.DataFrame(df1_data)
print df

我想添加名为" sym"。

的新列

条件 -

  1. 如果' e_id'列值不为null,则sym列值为' e_id'列值。
  2. 如果' r_id'列值不为空,则sym列值为' r_id'列值。
  3. 如果' e_id'和' r_id'两个列值都为null,然后从pandas dataframe中删除此特定行。
  4. 我尝试使用以下代码 -

    df1_data = {'e_id': {0:'101',1:'',2:'103',3:'',4:'105',5:''},
            'r_id': {0:'',1:'502',2:'',3:'504',4:'',5:'506'}}
    
    df=pd.DataFrame(df1_data)
    print df
    
    if df['e_id'].any():
        df['sym'] = df['e_id']
    print df
    
    if df['r_id'].any():
        df['sym'] = df['r_id']
    print df
    

    但它给了我错误的输出。

    预期产出 -

      e_id r_id  sym
    0  101       101
    1       502  502
    2  103       103
    3       504  504
    4  105       105
    5       506  506
    

3 个答案:

答案 0 :(得分:2)

<强> pandas
使用mask + fillna + assign

d1 = df.mask(df == '')
df.assign(sym=d1.e_id.fillna(d1.r_id)).dropna(subset=['sym'])

  e_id r_id  sym
0  101       101
1       502  502
2  103       103
3       504  504
4  105       105
5       506  506

工作原理

  • 我需要掩盖你的''值,假设你的意思是那些
  • 使用fillna我会e_id如果它不为空,否则如果r_id不为空
  • 如果新列为空,则
  • dropna subset=['sym']仅删除该行,如果e_idr_id都为空,则仅为空

<强> numpy
使用np.where + assign

e = df.e_id.values
r = df.r_id.values
df.assign(
    sym=np.where(
        e != '', e,
        np.where(r != '', r, np.nan)
    )
).dropna(subset=['sym'])

  e_id r_id  sym
0  101       101
1       502  502
2  103       103
3       504  504
4  105       105
5       506  506

numpy v2
从值重构数据框

v = df.values
m = (v != '').any(1)
v = v[m]
c1 = v[:, 0]
c2 = v[:, 1]
pd.DataFrame(
    np.column_stack([v, np.where(c1 != '', c1, c2)]),
    df.index[m], df.columns.tolist() + ['sym']
)

  e_id r_id  sym
0  101       101
1       502  502
2  103       103
3       504  504
4  105       105
5       506  506

时间

%%timeit
e = df.e_id.values
r = df.r_id.values
df.assign(sym=np.where(e != '', e, np.where(r != '', r, np.nan))).dropna(subset=['sym'])
1000 loops, best of 3: 1.23 ms per loop

%%timeit
d1 = df.mask(df == '')
df.assign(sym=d1.e_id.fillna(d1.r_id)).dropna(subset=['sym'])
100 loops, best of 3: 2.44 ms per loop

%%timeit
v = df.values
m = (v != '').any(1)
v = v[m]
c1 = v[:, 0]
c2 = v[:, 1]
pd.DataFrame(
    np.column_stack([v, np.where(c1 != '', c1, c2)]),
    df.index[m], df.columns.tolist() + ['sym']
)
1000 loops, best of 3: 204 µs per loop

答案 1 :(得分:2)

首先使用boolean indexing {/ 3>按any对两个空列进行过滤

SecureString

然后将maskcombine_first

一起使用
df = df[(df != '').any(1)]
#alternatively
#df = df[(df['e_id'] != '') | (df['r_id'] != '')]

带过滤的Numpy解决方案和numpy.where

df['sym'] = df['e_id'].mask(df['e_id'] == '').combine_first(df['r_id'])
print (df)

  e_id r_id  sym
0  101       101
1       502  502
2  103       103
3       504  504
4  105       105
5       506  506

答案 2 :(得分:0)

您可以使用pandas.DataFrame.mask'other'参数,从列“ e_id”开始,并在“ e_id”为“空”时将其值替换为“ r_id”值:

df['sym'] = df['e_id'].mask(df['e_id'] == '', other=df['r_id'], axis=0)

然后,您只需要删除sym为“空”的行

df = df[df.sym!='']