Python 排序,但如果值相同,则第二个变量具有均匀分布
我有两列:数据帧中的Col1和Col2。Col1的数字范围为1到100,Col2的数字范围为0和1 我希望以这样一种方式对这个数据帧进行排序,即按Col1对行进行排序。在我的例子中,我有几百万行,所以Col1值肯定会重复很多次 我可以使用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
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'])