Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 排序,但如果值相同,则第二个变量具有均匀分布_Python_Sorting_Pandas_Numpy - Fatal编程技术网

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

Python 排序,但如果值相同,则第二个变量具有均匀分布,python,sorting,pandas,numpy,Python,Sorting,Pandas,Numpy,我有两列:数据帧中的Col1和Col2。Col1的数字范围为1到100,Col2的数字范围为0和1 我希望以这样一种方式对这个数据帧进行排序,即按Col1对行进行排序。在我的例子中,我有几百万行,所以Col1值肯定会重复很多次 我可以使用data=data.sort\u values('Col1')根据Col1对值进行排序。例如,这可以提供: Col1 Col2 ... OR ... Col1 Col2 ... OR ... Col1 Col2 100 0 100

我有两列:数据帧中的Col1和Col2。Col1的数字范围为1到100,Col2的数字范围为0和1

我希望以这样一种方式对这个数据帧进行排序,即按Col1对行进行排序。在我的例子中,我有几百万行,所以Col1值肯定会重复很多次

我可以使用
data=data.sort\u values('Col1')
根据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/[任何其他库]有什么排序方法可以做到这一点吗?有什么算法可以做到这一点吗?

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

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

您必须在每组开始时生成好的排名,以更改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(01001000),'col2':randint(0,21000),})


我们可以使用
cumcount
,然后按col和count进行排序:

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

这取决于你所说的“均匀分布”是什么意思。您是否会应用一些必须通过特定阈值的特定测试?如果只需要“足够一致”或“不可预测”,可以在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'])

EA尝试此操作并
df['rk']=sum([list(range(n))表示cnt中的n])
给出了一个错误。你能查一下吗?我无法重现结果,我将代码放入块中以避免输入错误。错误信息是什么?它本质上是说您不能对列表列表执行
sum
<代码>总和([[1,1],[2,2]])也不起作用。它为+:'int'和'list'提供了不受支持的操作数类型。。它需要一个intsHm列表,所以我基本上希望(如果必要的话,很可能)当Col1具有相同的值时,0和1是均匀分布的。我的最终目标是,在我获取的任何数据块中(假设Col1=99的前10%的行),平均Col2应该是相同的。我得到前10%可能与1%-11%不同,因为这是离散数据。但从概率上来说就足够了。非常感谢你问我这个关于“如何统一”的问题。这让我意识到这个问题可能没有很好的定义。帮助我重新思考如何界定这个问题。
# 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'])