我有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 / [任何其他库]有没有可以执行此操作的排序方法?算法的任何想法都能做到这一点吗?
答案 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'])