pandas row操作只保留每行最右边的非零值

时间:2016-09-01 13:01:45

标签: python pandas dataframe

如何在数据框的每一行中保留最右边的数字?

a = [[1, 2, 0], [1, 3, 0], [1, 0, 0]]
df = pd.DataFrame(a, columns=['col1','col2','col3'])
df

      col1  col2    col3
row0    1   2       NaN
row1    1   3       0
row2    1   0       0

然后转型

      col1  col2    col3
row0    0   2       0
row1    0   3       0
row2    1   0       0

根据divakar的建议,我提出了以下建议:

import pandas as pd
a = [[1, 2, 0, None], 
     [1, 3, 0,0], 
     [1, 0, 0,0], 
     [1, 0, 0,0], 
     [1, 0, 0,0], 
     [0, 0, 0,1]]

df = pd.DataFrame(a, columns=['col1','col2','col3','col4'])
df.fillna(value=0,inplace=True) # Get rid of non numeric items
a

[[1, 2, 0, None],
 [1, 3, 0, 0],
 [1, 0, 0, 0],
 [1, 0, 0, 0],
 [1, 0, 0, 0],
 [0, 0, 0, 1]]

# Return index of first occurrence of maximum over requested axis.
# 0 or 'index' for row-wise, 1 or 'columns' for column-wise
df.idxmax(1)

0    col2
1    col2
2    col1
3    col1
4    col1
5    col4
dtype: object

创建一个矩阵来掩盖值

numberOfRows = df.shape[0]
df_mask= pd.DataFrame(columns=df.columns,index=np.arange(0, numberOfRows))
df_test.fillna(value=0,inplace=True) # Get rid of non numeric items

# Add mask entries
for row,col in enumerate(df.idxmax(1)):
   df_mask.loc[row,col] = 1

df_result=df*df_mask
df_result

col1    col2    col3    col4
0   0   2   0   0.0
1   0   3   0   0.0
2   1   0   0   0.0
3   1   0   0   0.0
4   1   0   0   0.0
5   0   0   0   1.0

3 个答案:

答案 0 :(得分:2)

以下是需要使用辅助函数的解决方法:

import pandas as pd

    #Helper functions
def last_number(lst):
    if all(map(lambda x: x == 0, lst)):
        return 0
    elif lst[-1] != 0:
        return len(lst)-1
    else:
        return last_number(lst[:-1])

def fill_others(lst):
    new_lst = [0]*len(lst)
    new_lst[last_number(lst)] = lst[last_number(lst)]
    return new_lst

#Data
a = [[1, 2, 0], [1, 3, 0], [1, 0, 0]]
df = pd.DataFrame(a, columns=['col1','col2','col3'])
df.fillna(0, inplace = True)

print df

   col1  col2  col3
0     1     2     0
1     1     3     0
2     1     0     0

#Application
print df.apply(lambda x: fill_others(x.values.tolist()), axis=1)

   col1  col2  col3
0     0     2     0
1     0     3     0
2     1     0     0

正如他们的名字所示,函数获取给定行中的最后一个数字,并用零填充其他值。

我希望这会有所帮助。

答案 1 :(得分:2)

在NumPy级别工作,这是使用broadcasting -

的一种矢量化方法
np.where(((a!=0).cumsum(1).argmax(1))[:,None] == np.arange(a.shape[1]),a,0)

示例运行 -

In [7]: a # NumPy array
Out[7]: 
array([[1, 2, 0],
       [1, 3, 0],
       [1, 0, 0]])

In [8]: np.where(((a!=0).cumsum(1).argmax(1))[:,None] == np.arange(a.shape[1]),a,0)
Out[8]: 
array([[0, 2, 0],
       [0, 3, 0],
       [1, 0, 0]])

将其移植到pandas,我们会有类似的实现 -

idx = (df!=0).values.cumsum(1).argmax(1)
df_out = df*(idx[:,None] == np.arange(df.shape[1]))

示例运行 -

In [19]: df
Out[19]: 
   col1  col2  col3  col4
0     1     2     0   0.0
1     1     3     0   0.0
2     2     2     2   0.0
3     1     0     0   0.0
4     1     0     0   0.0
5     0     0     0   1.0

In [20]: idx = (df!=0).values.cumsum(1).argmax(1)

In [21]: df*(idx[:,None] == np.arange(df.shape[1]))
Out[21]: 
   col1  col2  col3  col4
0     0     2     0   0.0
1     0     3     0   0.0
2     0     0     2   0.0
3     1     0     0   0.0
4     1     0     0   0.0
5     0     0     0   1.0

答案 2 :(得分:1)

您可以从左侧"填充空值"然后获取最后一列的值:

In [49]: df.fillna(axis=0, method='bfill')['col3']
Out[49]: 
0    0.0
1    0.0
2    0.0
Name: col3, dtype: float64

完整示例

In [50]: a = [[1, 2, None], [1, 3, 0], [0, 0, 0]]

In [51]: df = pd.DataFrame(a, columns=['col1','col2','col3'])

In [52]: df.fillna(axis=0, method='bfill')['col3']
Out[52]: 
0    0.0
1    0.0
2    0.0
Name: col3, dtype: float64