我需要将我的数据集分成两个部分:80% 和 20%。
我的数据集如下所示:
PersonID Timestamp Foo1 Foo2 Foo3 Label
1 1626184812 6 5 2 1
2 616243602 8 5 2 1
2 634551342 4 8 3 1
2 1531905378 3 8 8 1
3 616243602 10 7 8 2
3 634551342 7 5 8 2
4 1626184812 7 9 1 2
4 616243602 5 7 9 1
4 634551342 9 1 6 2
4 1531905378 3 3 3 1
4 768303369 6 1 7 2
5 1626184812 5 7 8 2
5 616243602 6 2 6 1
6 1280851467 3 2 2 2
7 1626184812 10 1 10 1
7 616243602 6 3 6 2
7 1531905378 9 5 7 2
7 634551342 3 7 9 1
8 616243602 8 7 4 2
8 634551342 2 2 4 1
(注意,您应该可以使用 pd.read_clipboard()
to get this data into a dataframe。)
我想要完成的是:
Timestamp
组织,这意味着 旧 数据应在训练中,新 数据应在测试中立>
前两点在下面的最小示例中完成。第三点是我遇到的问题。例如,使用 sklearn's train_test_split
:
下面的最小示例:
# Imports
import pandas as pd
from sklearn.model_selection import train_test_split
# Normal split
x = pd.read_clipboard()
train, test = train_test_split(x, train_size=0.8, test_size=0.20, random_state=8)
# Organizing it by time
x = pd.read_clipboard()
x = x.sort_values(by='Timestamp')
train, test = train_test_split(x, train_size=0.8, test_size=0.20, random_state=8)
我正在努力弄清楚如何对数据框进行分组,以便一个人不会在训练和测试之间分开。例如,在上面,PersonID
数据帧中的每个 test
也 出现在 train
数据帧中。如何在确保 PersonID 不被拆分的同时保持 about 的比例相等?
答案 0 :(得分:2)
这两个条件很难严格地放在一起:训练中的旧时间戳与单个 PersonID 训练或测试,但不能同时进行。这里有两个想法。
对于火车中较旧的时间戳,可能不是最严格的解决方案,但您可以尝试获取 max
(或 {{1} } 或 min
由您决定)每个 personID 的时间戳和 mean
,然后 count
最大到 sort_values
计数。使用 cumsum
的 max
乘以 80% 的拆分训练测试。
cumsum
然后你得到
# calculate the cumsum of count
s = (
x.groupby('PersonID')
['Timestamp'].agg(['max','count'])
.sort_values('max')
['count'].cumsum()
)
s = s<s.max()*0.8 # get boolean mask for train personID
另一种选择是使用 sklearn.model_selection.GroupShuffleSplit 像:
train = x.loc[x['PersonID'].isin(s[s].index)]
print(train)
# PersonID Timestamp Foo1 Foo2 Foo3 Label
# 0 1 1626184812 6 5 2 1
# 1 2 616243602 8 5 2 1
# 2 2 634551342 4 8 3 1
# 3 2 1531905378 3 8 8 1
# 4 3 616243602 10 7 8 2
# 5 3 634551342 7 5 8 2
# 6 4 1626184812 7 9 1 2
# 7 4 616243602 5 7 9 1
# 8 4 634551342 9 1 6 2
# 9 4 1531905378 3 3 3 1
# 10 4 768303369 6 1 7 2
# 13 6 1280851467 3 2 2 2
# 18 8 616243602 8 7 4 2
# 19 8 634551342 2 2 4 1
test = x.loc[x['PersonID'].isin(s[~s].index)]
print(test)
# PersonID Timestamp Foo1 Foo2 Foo3 Label
# 11 5 1626184812 5 7 8 2
# 12 5 616243602 6 2 6 1
# 14 7 1626184812 10 1 10 1
# 15 7 616243602 6 3 6 2
# 16 7 1531905378 9 5 7 2
# 17 7 634551342 3 7 9 1
并增加参数 from sklearn.model_selection import GroupShuffleSplit
gss = GroupShuffleSplit(n_splits=1, train_size=.8, random_state=42)
for train_idx, test_idx in gss.split(x.index, groups=x['PersonID']):
print("TRAIN ID:", x.loc[train_idx,'PersonID'].unique(),
", Timestamp:", x.loc[train_idx,'Timestamp'].mean(),)
print("TEST ID:", x.loc[test_idx,'PersonID'].unique(),
", Timestamp:", x.loc[test_idx,'Timestamp'].mean())
# TRAIN ID: [1 3 4 5 7 8] , Timestamp: 997267296.9375
# TEST ID: [2 6] , Timestamp: 1015887947.25
并保留为训练提供最小均值或为测试提供最高均值的分割。