如果值相同,则为第二个变量排序但分布均匀

时间:2017-02-21 11:12:54

标签: python sorting pandas numpy

我有2列:Pandas数据帧中的Col1,Col2。 Col1的数字从1到100,Col2的数字为0和1。

我想以这样的方式对这个数据框进行排序,即行按Col1排序。在我的情况下,我有几百万行,所以绝对Col1值将重复多次。

我可以根据Col1对data = data.sort_values('Col1')进行排序。例如,这可以给出:

Col1 Col2 ... OR ... Col1 Col2 ... OR ... Col1 Col2
100  0               100  1               100  0
100  0               100  1               100  0
100  1               100  1               100  0
100  0               100  1               100  0
100  1               100  0               100  1
100  1               100  0               100  1
100  1               100  0               100  1
100  0               100  0               100  1
99   1               99   1               99   1
...                  ...                  ...

根据我使用的排序算法(快速排序,合并排序等),当Col1 = 100时,Col2可能有很多可能的分布。

在我的Col1值相同的部分中,我希望我的Col2的分布是统一的,如下所示:

Col1 Col2
100  0
100  1
100  0
100  1
100  0
100  1
100  0
100  1
99   1
...

python / numpy / pandas / [任何其他库]有没有可以执行此操作的排序方法?算法的任何想法都能做到这一点吗?

4 个答案:

答案 0 :(得分:1)

您必须在每组的开头为0和1生成良好等级:

df=pd.DataFrame({'col1':randint(0,100,1000),'col2':randint(0,2,1000),}) 
df.sort_values(['col1','col2'],inplace=True)
cnt= df.groupby(['col1','col2']).col1.count()
df['rk']=np.hstack([list(range(n)) for n in cnt])
df.sort_values(['col1','rk'],inplace=True)

一些解释:

首先排序df

df.sort_values(['col1','col2'],inplace=True)

然后计算每个值:

cnt= df.groupby(['col1','col2']).col1.count()

并排名:

df['rk']=np.hstack([list(range(n)) for n in cnt])

解决方案是:

df.sort_values(['col1','rk'],inplace=True)

df=pd.DataFrame({'col1':randint(0,100,1000),'col2':randint(0,2,1000),})

     col1  col2  rk
161     0     0   0
1       0     1   0
253     0     0   1
118     0     1   1
471     0     0   2
391     0     1   2
582     0     0   3
444     0     1   3
579     0     1   4
735     0     1   5
887     0     1   6
111     1     0   0
57      1     1   0
......

答案 1 :(得分:0)

我能想到的一个想法是创建一个新列,其值代表顺序:

offset_dict = defaultdict(lambda: defaultdict(lambda: 2))

def get_offset(row):
    step = offset_dict[row["Col1"]][row["Col2"]]
    offset_dict[row["Col1"]][row["Col2"]] += 1
    return row["Col1"] + 1.0/step

df["offset"] = df.apply(get_offset, axis=1)
df = df.sort_values("offset")

输入表格:

    Col1  Col2
0    100     1
1    100     1
2    100     1
3     99     1
4    100     0
5    100     0
6     99     1
7     99     0
8     99     0
9    100     0
10    99     0
11   100     1
12   100     1
13   100     0
14   100     0

输出将是:

    Col1  Col2      offset
10    99     0   99.250000
6     99     1   99.333333
8     99     0   99.333333
3     99     1   99.500000
7     99     0   99.500000
12   100     1  100.166667
14   100     0  100.166667
11   100     1  100.200000
13   100     0  100.200000
2    100     1  100.250000
9    100     0  100.250000
1    100     1  100.333333
5    100     0  100.333333
0    100     1  100.500000
4    100     0  100.500000

答案 2 :(得分:0)

我们可以使用cumcount,然后按col排序,并计算:

import pandas as pd
import numpy as np
#data from B. M.

df=pd.DataFrame({'col1':np.random.randint(0,100,1000),'col2':np.random.randint(0,2,1000)}) 

#make a new column, with the cumulative count for each of col1:col2
df['values'] = df.groupby(['col1','col2']).cumcount()

#sort by the col1, and values:
df.sort_values(['col1', 'values'])

    col1    col2    values
61  0   1   0
213 0   0   0
173 0   1   1
473 0   0   1
266 0   1   2

如果它们非常不平衡,这将失败!

作为一个快速的黑客,按不平衡排序,我们可以通过每个值的计数来纠正,并将我们的指数除以:

#make a new column, with the cumulative count for each of col1:col2
df['values'] = df.groupby(['col1','col2']).cumcount()

#sort by the col1, and values:
df.sort_values(['col1', 'values'])
#merge in a count of each value
df = df.merge(df.groupby(['col1', 'col2']).size().reset_index())
#make a key of index/count
df['sortkey'] = df['values']/df[0]
#sort
df.sort_values(['col1', 'sortkey'])

    col1    col2    values  sortkey 0
393 0   0   0   0.000000    3
812 0   1   0   0.000000    4
813 0   1   1   0.250000    4
394 0   0   1   0.333333    3
814 0   1   2   0.500000    4

答案 3 :(得分:0)

这取决于“均匀分布”的含义。您是否会应用一些必须通过特定阈值的特定测试?如果你只需要“足够均匀”或“不可预测”,你可以在Col1的每个值中随机化。

# setup
import pandas as pd
import numpy as np
df=pd.DataFrame({'col1':randint(0,100,1000),'col2':randint(0,2,1000),})

# add a column with random numbers
df['random_col'] = np.random.random(len(df))

# two-level sort 
df.sort_values(['col1','random_col'])