Python 在panda数据帧中获得n个最小的行

Python 在panda数据帧中获得n个最小的行,python,pandas,dataframe,Python,Pandas,Dataframe,我的数据框如下所示: A B C D date 2015-01-01 1 1 2 3 2015-01-02 1 2 3 3 2015-01-03 1 2 1 3 2015-01-04 3 2 1 1 2015-01-05 3 2 2 1 2015-01-06 1 1 2 3 2015-01-07 1 2 3 3 2015-01-08 1 2 1 3 2015-01-0

我的数据框如下所示:

            A  B  C  D
date                  
2015-01-01  1  1  2  3
2015-01-02  1  2  3  3
2015-01-03  1  2  1  3
2015-01-04  3  2  1  1
2015-01-05  3  2  2  1
2015-01-06  1  1  2  3
2015-01-07  1  2  3  3
2015-01-08  1  2  1  3
2015-01-09  3  2  1  1
2015-01-10  3  2  2  1
2015-01-11  3  2  2  1
基本规则:我想为每行确定2个最小值,并将这些值设置为1。其他值应设置为0

其他规则:

1 1 1 1  should be 1 1 1 1
1 2 2 2  should be 1 1 1 1
1 2 2 3  should be 1 1 1 0
1 2 3 4  should be 1 1 0 0
我希望您能够遵循规则,对于开始时的数据帧,结果应该是

date        A   B   C   D
2015-01-01  1   1   0   0
2015-01-02  1   1   0   0
2015-01-03  1   0   1   0
2015-01-04  0   0   1   1
2015-01-05  0   1   1   1
2015-01-06  1   1   0   0
2015-01-07  1   1   0   0
2015-01-08  1   0   1   0
2015-01-09  0   0   1   1
2015-01-10  0   1   1   1
2015-01-11  0   1   1   1
编辑

“也许你想用class='first'方法排名,我想这是可行的–EdChum” 数据帧的结果:

            A  B  C  D
date                  
2015-01-01  1  2  3  4
2015-01-02  1  2  3  4
2015-01-03  1  3  2  4
2015-01-04  4  3  1  2
2015-01-05  4  2  3  1
2015-01-06  1  2  3  4
2015-01-07  1  2  3  4
2015-01-08  1  3  2  4
2015-01-09  4  3  1  2
2015-01-10  4  2  3  1
2015-01-11  4  2  3  1

我想这正是你想要的:

In [3]:
mask = df.rank(method='dense', axis=1) <= 2
df[mask] = 1
df[~mask] = 0
df

Out[3]:
            A  B  C  D
date                  
2015-01-01  1  1  1  0
2015-01-02  1  1  0  0
2015-01-03  1  1  1  0
2015-01-04  0  1  1  1
2015-01-05  0  1  1  1
2015-01-06  1  1  1  0
2015-01-07  1  1  0  0
2015-01-08  1  1  1  0
2015-01-09  0  1  1  1
2015-01-10  0  1  1  1
2015-01-11  0  1  1  1
[3]中的


mask=df.rank(method='densite',axis=1)我想这就是你想要的:

In [3]:
mask = df.rank(method='dense', axis=1) <= 2
df[mask] = 1
df[~mask] = 0
df

Out[3]:
            A  B  C  D
date                  
2015-01-01  1  1  1  0
2015-01-02  1  1  0  0
2015-01-03  1  1  1  0
2015-01-04  0  1  1  1
2015-01-05  0  1  1  1
2015-01-06  1  1  1  0
2015-01-07  1  1  0  0
2015-01-08  1  1  1  0
2015-01-09  0  1  1  1
2015-01-10  0  1  1  1
2015-01-11  0  1  1  1
[3]中的


mask=df.rank(method='dense',axis=1)如果您想扩展超过4列,也许您可以尝试以下方法,前面解决方案中的mask思想也是我实现它的方式,但是您可以指定您想要两个最小的值:

mask = df.apply(lambda x: x.isin(x.nsmallest(2)), axis=1)
df[mask] = 1
df[~mask] = 0
df

            A   B   C   D
2015-01-01  1   1   0   0
2015-01-02  1   1   0   0
2015-01-03  1   0   1   0
2015-01-04  0   0   1   1
2015-01-05  0   1   1   1
2015-01-06  1   1   0   0
2015-01-07  1   1   0   0
2015-01-08  1   0   1   0
2015-01-09  0   0   1   1
2015-01-10  0   1   1   1
2015-01-11  0   1   1   1

我担心此解决方案在更大数据集上的性能,但它应该会为您找到您想要的答案

如果您想扩展超过4列,也许您可以尝试以下方法,我也会采用以前解决方案中的掩码思想来实现它,但是,您可以指定需要两个最小的值:

mask = df.apply(lambda x: x.isin(x.nsmallest(2)), axis=1)
df[mask] = 1
df[~mask] = 0
df

            A   B   C   D
2015-01-01  1   1   0   0
2015-01-02  1   1   0   0
2015-01-03  1   0   1   0
2015-01-04  0   0   1   1
2015-01-05  0   1   1   1
2015-01-06  1   1   0   0
2015-01-07  1   1   0   0
2015-01-08  1   0   1   0
2015-01-09  0   0   1   1
2015-01-10  0   1   1   1
2015-01-11  0   1   1   1

我担心这个解决方案在更大的数据集上的性能,但它应该能为您找到您想要的答案

很好,但是否有可能得到一个更通用的解决方案来处理第n个最低值(在上面的示例中,n=2)并且可以处理超过4列?我意识到这只适用于行中的值总数等于大小除以
n
,我认为更通用的解决方案是使用
apply
,但它不会被矢量化,因此对于大型DFS来说速度会很慢。值是否始终为整数且从1到4?我认为使用
rank
可以实现您想要的功能,请参阅我的editNo,示例是将rank应用于原始数据帧,结果将是1到max=列数(但如果一行中有两个值为requal,则结果会更小).很好,但是有没有可能得到一个更通用的解决方案,可以处理第n个最小值(在上面的示例中,n=2)并且可以处理4列以上的列?我意识到这只适用于行中的值总数等于大小除以
n
,一个更通用的解决方案是使用
apply
,我想,但它不会被矢量化,因此对于较大的DFS来说速度会很慢。值是否始终是整数,从1到4?我认为使用
rank
可以满足您的需要,请参阅我的editNo,示例是将rank应用于原始数据帧,结果将是1到max=列数(但如果一行中有两个值为requal,则该值将更小)。