将数据框拆分为唯一值块
Split dataframe into chunks of unique values
我有两个组(A
和 B
)的数据框,在这些组中,有 6 个子组(a
、b
、c
、d
、e
和 f
)。以下示例数据:
index group subgroup value
0 A a 1
1 A b 1
2 A c 1
3 A d 1
4 A e 1
5 A f 1
6 B a 1
7 B b 1
8 B c 1
9 B d 1
10 B e 1
11 B f 1
... ... ... ...
虽然我在这里只列出了 12 行,但实际数据集中有 300 行。我正在尝试将数据框随机拆分为 50 批 6 个值。重要的是,每个批次应该有每个子组 1 个,并且组的分布大致相等。
期望的输出:
index group subgroup batch
0 A a 1
1 A b 1
2 A c 1
3 B d 1
4 B e 1
5 B f 1
6 A d 2
7 A e 2
8 A f 2
9 B a 2
10 B b 2
11 B c 2
... ... ... ...
在我的数据集中,有 150 个 A
和 150 个 B
,但不幸的是,没有相同数量的子组(例如,我有 25 a
s, 27 b
s, 23 c
s, etc. contained with A
) 因此,如果批次 1-48 包含唯一的子组(即每个 a-f 中的 1 个),那将是首选),但是第 49 批和第 50 批的剩菜没有平均分配——事后我需要以某种方式手动随机化这些!最重要的是一个batch中每个子组都有一个,但不太重要的是一个batch中恰好有3个A
s和3个B
s。谢谢!
此解决方案从批次 1-48 的每个 subgroup
中准确挑选出一个元素。第 49-50 批是随机挑选的。来自 A
s 和 B
s 的数字不被考虑。
逻辑
- 通过对每个子组的索引执行随机排列来打乱每个子组。
- 每个子组的第一个元素构成第一批,第二个元素构成第二批,依此类推
代码
# data
df = pd.DataFrame(
{"group": ["A"]*150 + ["B"]*150,
"subgroup": ["a", "b", "c", "d", "e", "f"] * 48 + ["a", "b"]*3 + ["c", "d"]*2 + ["e", "f"],
"value": range(0, 3000, 10)}
)
df.index.name = "index"
# length parameters
subgroups = df["subgroup"].unique() # np.array(["a", "b", "c", "d", "e", "f"])
l = len(subgroups) # 6
m = 48 # number of regular batches
n = int(len(df) / l) # 300/6=50
# storage
arr = np.zeros((m, l)) # for batch 1-48
ls_rest = [] # for batch 49-50
# shuffle
for i, subgroup in enumerate(subgroups):
perm = np.random.permutation(df.index[df["subgroup"] == subgroup])
arr[:, i] = perm[:m] # for regular batches
ls_rest += list(perm[m:]) # for the rest
# assign batch 1-48
df["batch"] = 0
for i in range(m):
df.loc[arr[i,:], "batch"] = i+1
# assign batch 49-50
for i in range(n-m):
df.loc[ls_rest[i*l:(i+1)*l], "batch"] = m+1+i
# sorting is omitted
输出
常规批次
可以看到每个批次中每个子组确实有一个元素。
print(df.sort_values(["batch", "subgroup"]).head(13))
group subgroup value batch
index
48 A a 480 1
13 A b 130 1
134 A c 1340 1
171 B d 1710 1
262 B e 2620 1
5 A f 50 1
240 B a 2400 2
291 B b 2910 2
152 B c 1520 2
93 A d 930 2
136 A e 1360 2
59 A f 590 2
24 A a 240 3
其余
print(df.sort_values(["batch", "subgroup"]).tail(13))
group subgroup value batch
index
29 A f 290 48
120 A a 1200 49
222 B a 2220 49
276 B a 2760 49
61 A b 610 49
133 A b 1330 49
289 B b 2890 49
98 A c 980 50
206 B c 2060 50
45 A d 450 50
295 B d 2950 50
166 B e 1660 50
233 B f 2330 50
我有两个组(A
和 B
)的数据框,在这些组中,有 6 个子组(a
、b
、c
、d
、e
和 f
)。以下示例数据:
index group subgroup value
0 A a 1
1 A b 1
2 A c 1
3 A d 1
4 A e 1
5 A f 1
6 B a 1
7 B b 1
8 B c 1
9 B d 1
10 B e 1
11 B f 1
... ... ... ...
虽然我在这里只列出了 12 行,但实际数据集中有 300 行。我正在尝试将数据框随机拆分为 50 批 6 个值。重要的是,每个批次应该有每个子组 1 个,并且组的分布大致相等。
期望的输出:
index group subgroup batch
0 A a 1
1 A b 1
2 A c 1
3 B d 1
4 B e 1
5 B f 1
6 A d 2
7 A e 2
8 A f 2
9 B a 2
10 B b 2
11 B c 2
... ... ... ...
在我的数据集中,有 150 个 A
和 150 个 B
,但不幸的是,没有相同数量的子组(例如,我有 25 a
s, 27 b
s, 23 c
s, etc. contained with A
) 因此,如果批次 1-48 包含唯一的子组(即每个 a-f 中的 1 个),那将是首选),但是第 49 批和第 50 批的剩菜没有平均分配——事后我需要以某种方式手动随机化这些!最重要的是一个batch中每个子组都有一个,但不太重要的是一个batch中恰好有3个A
s和3个B
s。谢谢!
此解决方案从批次 1-48 的每个 subgroup
中准确挑选出一个元素。第 49-50 批是随机挑选的。来自 A
s 和 B
s 的数字不被考虑。
逻辑
- 通过对每个子组的索引执行随机排列来打乱每个子组。
- 每个子组的第一个元素构成第一批,第二个元素构成第二批,依此类推
代码
# data
df = pd.DataFrame(
{"group": ["A"]*150 + ["B"]*150,
"subgroup": ["a", "b", "c", "d", "e", "f"] * 48 + ["a", "b"]*3 + ["c", "d"]*2 + ["e", "f"],
"value": range(0, 3000, 10)}
)
df.index.name = "index"
# length parameters
subgroups = df["subgroup"].unique() # np.array(["a", "b", "c", "d", "e", "f"])
l = len(subgroups) # 6
m = 48 # number of regular batches
n = int(len(df) / l) # 300/6=50
# storage
arr = np.zeros((m, l)) # for batch 1-48
ls_rest = [] # for batch 49-50
# shuffle
for i, subgroup in enumerate(subgroups):
perm = np.random.permutation(df.index[df["subgroup"] == subgroup])
arr[:, i] = perm[:m] # for regular batches
ls_rest += list(perm[m:]) # for the rest
# assign batch 1-48
df["batch"] = 0
for i in range(m):
df.loc[arr[i,:], "batch"] = i+1
# assign batch 49-50
for i in range(n-m):
df.loc[ls_rest[i*l:(i+1)*l], "batch"] = m+1+i
# sorting is omitted
输出
常规批次
可以看到每个批次中每个子组确实有一个元素。
print(df.sort_values(["batch", "subgroup"]).head(13))
group subgroup value batch
index
48 A a 480 1
13 A b 130 1
134 A c 1340 1
171 B d 1710 1
262 B e 2620 1
5 A f 50 1
240 B a 2400 2
291 B b 2910 2
152 B c 1520 2
93 A d 930 2
136 A e 1360 2
59 A f 590 2
24 A a 240 3
其余
print(df.sort_values(["batch", "subgroup"]).tail(13))
group subgroup value batch
index
29 A f 290 48
120 A a 1200 49
222 B a 2220 49
276 B a 2760 49
61 A b 610 49
133 A b 1330 49
289 B b 2890 49
98 A c 980 50
206 B c 2060 50
45 A d 450 50
295 B d 2950 50
166 B e 1660 50
233 B f 2330 50