最小类大小的样本选择



我希望每个字母至少有4个样品。但是,应该按id选择样本,以便首先使用匹配度最高的样本。(行级别的最大值)。

我已经尝试将总和拖动到行水平,然后从最高值到最低值采样。然而,这种方法不能保证最小的班级规模。可以随机选择剩余的样本来填充类。

有谁知道我如何在熊猫中解决这个问题吗?


id  A   B   C   D   E
0   1   1   0   0   0
1   1   0   0   1   0
2   0   1   1   0   0
3   0   1   0   0   0
4   1   1   1   0   1
5   0   1   0   1   1
6   0   0   0   1   1
7   1   0   0   0   1
8   1   0   1   1   1
9   0   0   0   0   0
10  1   1   0   0   0
11  1   0   0   1   0
12  0   1   1   0   0
13  0   1   0   0   0
14  1   1   1   0   1
15  0   1   0   1   1
16  0   0   0   1   1
17  1   0   0   0   1
18  1   0   1   1   1
19  0   0   0   0   0

sum 10  10  6   8   10

如果我理解正确的话,您试图从每个具有最高指数的字母中挑选至少4个样本。

选择最高索引的一种方法是根据索引出现的列数对索引进行排序-

high_index = []
for col in df.columns:
high_index.append(sorted(df[df[col] > 0].index.values, reverse=True))

这为您提供了每个列的最高索引-即对于A,带1的最高索引是18

# print(high_index)
[[18, 17, 14, 11, 10, 8, 7, 4, 1, 0],
[15, 14, 13, 12, 10, 5, 4, 3, 2, 0],
[18, 14, 12, 8, 4, 2],
[18, 16, 15, 11, 8, 6, 5, 1],
[18, 17, 16, 15, 14, 8, 7, 6, 5, 4]]

然后你可以根据它们出现的次数对每个索引进行排名-

rank_index = list(enumerate([sum([x in y for y in high_index]) for x in range(df.index.size)]))
# print(rank_index)
[(0, 2),
(1, 2),
(2, 2),
(3, 1),
(4, 4),
(5, 3),
(6, 2),
(7, 2),
(8, 4),
(9, 0),
(10, 2),
(11, 2),
(12, 2),
(13, 1),
(14, 4),
(15, 3),
(16, 2),
(17, 2),
(18, 4),
(19, 0)]

或者,索引0以2列1出现(您也可以通过对axis=1求和得到相同的结果)

如果按这些秩重新排序df,那么最小秩为4或更多的所有行都可以用于您的样本

reordered_index = [x for x, y in sorted(rank_index, reverse=True, key=lambda x: x[1])]
df_2 = df.loc[reordered_index, :]
df_2 = df_2.cumsum()
df_2['min_samples'] = df_2.min(axis=1)
# print(df_2)
A   B  C  D   E  min_samples
id                               
4    1   1  1  0   1            0
8    2   1  2  1   2            1
14   3   2  3  1   3            1
18   4   2  4  2   4            2
5    4   3  4  3   5            3
15   4   4  4  4   6            4
0    5   5  4  4   6            4
1    6   5  4  5   6            4
2    6   6  5  5   6            5
6    6   6  5  6   7            5
7    7   6  5  6   8            5
10   8   7  5  6   8            5
11   9   7  5  7   8            5
12   9   8  6  7   8            6
16   9   8  6  8   9            6
17  10   8  6  8  10            6
3   10   9  6  8  10            6
13  10  10  6  8  10            6
9   10  10  6  8  10            6
19  10  10  6  8  10            6

您可以选择的最小示例是df_2的前6行。

这就是我从你的问题中理解的。数据框为df

创建matches列:

df = df.assign(matches=df.sum(axis=1))

对包含字母的行按匹配次数排序:

letter = "A"
ans = df[df[letter] == 1].sort_values(by="matches", ascending=False)

如果你需要一个随机的样本:

n = 4
ans = ans.sample(n)

最后,如果样本需要再次按匹配项排序:

ans = ans.sort_values(by="matches", ascending=False)

Forletter == "B":

>>> ans
A  B  C  D  E  matches
15  0  1  0  1  1        3
10  1  1  0  0  0        2
0   1  1  0  0  0        2
3   0  1  0  0  0        1

最新更新