【发布时间】:2014-07-31 14:05:26
【问题描述】:
我有一个相当大的数据框形式的数据集,我想知道如何将数据框分成两个随机样本(80% 和 20%)用于训练和测试。
谢谢!
【问题讨论】:
标签: python python-2.7 pandas dataframe
我有一个相当大的数据框形式的数据集,我想知道如何将数据框分成两个随机样本(80% 和 20%)用于训练和测试。
谢谢!
【问题讨论】:
标签: python python-2.7 pandas dataframe
我会使用 K 折交叉验证。
事实证明,它比train_test_split 提供了更好的结果,这是一篇关于如何从文档本身中将其与 sklearn 一起应用的文章:https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.KFold.html
【讨论】:
如果您想将其拆分为训练、测试和验证集,您可以使用此功能:
from sklearn.model_selection import train_test_split
import pandas as pd
def train_test_val_split(df, test_size=0.15, val_size=0.45):
temp, test = train_test_split(df, test_size=test_size)
total_items_count = len(df.index)
val_length = total_items_count * val_size
new_val_propotion = val_length / len(temp.index)
train, val = train_test_split(temp, test_size=new_val_propotion)
return train, test, val
【讨论】:
scikit learn's train_test_split 是一个不错的选择 - 它将两个 numpy 数组拆分为数据帧。
from sklearn.model_selection import train_test_split
train, test = train_test_split(df, test_size=0.2)
【讨论】:
from sklearn.model_selection import train_test_split。
from sklearn.cross_validation import train_test_split
DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20. "This module will be removed in 0.20.", DeprecationWarning)
无需转换为 numpy。只需使用 pandas df 进行拆分,它将返回一个 pandas df。
from sklearn.model_selection import train_test_split
train, test = train_test_split(df, test_size=0.2)
如果你想把 x 和 y 分开
X_train, X_test, y_train, y_test = train_test_split(df[list_of_x_cols], df[y_col],test_size=0.2)
如果你想分割整个df
X, y = df[list_of_x_cols], df[y_col]
【讨论】:
就我而言,我想在 Train、test 和 dev 中使用特定数字拆分数据框。我在这里分享我的解决方案
首先,为数据框分配一个唯一的 id(如果不存在)
import uuid
df['id'] = [uuid.uuid4() for i in range(len(df))]
这是我的拆分号码:
train = 120765
test = 4134
dev = 2816
分割函数
def df_split(df, n):
first = df.sample(n)
second = df[~df.id.isin(list(first['id']))]
first.reset_index(drop=True, inplace = True)
second.reset_index(drop=True, inplace = True)
return first, second
现在拆分为训练、测试、开发
train, test = df_split(df, 120765)
test, dev = df_split(test, 4134)
【讨论】:
shuffle = np.random.permutation(len(df))
test_size = int(len(df) * 0.2)
test_aux = shuffle[:test_size]
train_aux = shuffle[test_size:]
TRAIN_DF =df.iloc[train_aux]
TEST_DF = df.iloc[test_aux]
【讨论】:
我会使用 scikit-learn 自己的 training_test_split,并从索引生成它
from sklearn.model_selection import train_test_split
y = df.pop('output')
X = df
X_train,X_test,y_train,y_test = train_test_split(X.index,y,test_size=0.2)
X.iloc[X_train] # return dataframe train
【讨论】:
cross_validation 模块现已弃用:DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.
df 其 output 列是字符串时会出错。我得到TypeError: '<' not supported between instances of 'str' and 'float'。看来y 需要是DataFrame 而不是Series。实际上,在 train_test_split 中附加 .to_frame() 的定义或 y 的参数 y 是有效的。如果您使用的是stratify = y,则需要确保此y 也是DataFrame。如果我改为定义y = df[["output"]] 和X = df.drop("output", axis = 1),那么它也可以;这与将.to_frame() 附加到y 的定义中基本相同。
您需要将 pandas 数据帧转换为 numpy 数组,然后将 numpy 数组转换回数据帧
import pandas as pd
df=pd.read_csv('/content/drive/My Drive/snippet.csv', sep='\t')
from sklearn.model_selection import train_test_split
train, test = train_test_split(df, test_size=0.2)
train1=pd.DataFrame(train)
test1=pd.DataFrame(test)
train1.to_csv('/content/drive/My Drive/train.csv',sep="\t",header=None, encoding='utf-8', index = False)
test1.to_csv('/content/drive/My Drive/test.csv',sep="\t",header=None, encoding='utf-8', index = False)
【讨论】:
要拆分成两个以上的类,例如训练、测试和验证,可以这样做:
probs = np.random.rand(len(df))
training_mask = probs < 0.7
test_mask = (probs>=0.7) & (probs < 0.85)
validatoin_mask = probs >= 0.85
df_training = df[training_mask]
df_test = df[test_mask]
df_validation = df[validatoin_mask]
这会将大约 70% 的数据用于训练,15% 用于测试,15% 用于验证。
【讨论】:
您可以使用~(波浪号运算符)排除使用df.sample()采样的行,让pandas单独处理索引的采样和过滤,以获得两组。
train_df = df.sample(frac=0.8, random_state=100)
test_df = df[~df.index.isin(train_df.index)]
【讨论】:
上面有很多很好的答案,所以我只想再添加一个示例,以防您想仅使用 numpy 库来指定训练集和测试集的确切样本数。
# set the random seed for the reproducibility
np.random.seed(17)
# e.g. number of samples for the training set is 1000
n_train = 1000
# shuffle the indexes
shuffled_indexes = np.arange(len(data_df))
np.random.shuffle(shuffled_indexes)
# use 'n_train' samples for training and the rest for testing
train_ids = shuffled_indexes[:n_train]
test_ids = shuffled_indexes[n_train:]
train_data = data_df.iloc[train_ids]
train_labels = labels_df.iloc[train_ids]
test_data = data_df.iloc[test_ids]
test_labels = data_df.iloc[test_ids]
【讨论】:
Pandas 随机样本也可以使用
train=df.sample(frac=0.8,random_state=200) #random state is a seed value
test=df.drop(train.index)
【讨论】:
random_statearg 在做什么?
test 将被随机选择,但行将按其原始顺序排列。 sklearn 方法对训练和测试进行了洗牌。
test 集,则很容易解决此限制,正如此处stackoverflow.com/questions/29576430/shuffle-dataframe-rows 所指出的那样。 test=df.drop(train.index).sample(frac=1.0)
有很多方法可以创建训练/测试甚至验证样本。
案例一:经典方式train_test_split 没有任何选项:
from sklearn.model_selection import train_test_split
train, test = train_test_split(df, test_size=0.3)
案例 2:非常小的数据集(
from sklearn.model_selection import KFold
kf = KFold(n_splits=10, random_state=0)
y_hat_all = []
for train_index, test_index in kf.split(X, y):
reg = RandomForestRegressor(n_estimators=50, random_state=0)
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
clf = reg.fit(X_train, y_train)
y_hat = clf.predict(X_test)
y_hat_all.append(y_hat)
案例 3a:用于分类目的的不平衡数据集。按照案例1,下面是等效的解决方案:
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, test_size=0.3)
案例 3b:用于分类目的的不平衡数据集。按照案例2,这里是等效的解决方案:
from sklearn.model_selection import StratifiedKFold
kf = StratifiedKFold(n_splits=10, random_state=0)
y_hat_all = []
for train_index, test_index in kf.split(X, y):
reg = RandomForestRegressor(n_estimators=50, random_state=0)
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
clf = reg.fit(X_train, y_train)
y_hat = clf.predict(X_test)
y_hat_all.append(y_hat)
案例 4:您需要在大数据上创建训练/测试/验证集来调整超参数(60% 训练、20% 测试和 20% 验证)。
from sklearn.model_selection import train_test_split
X_train, X_test_val, y_train, y_test_val = train_test_split(X, y, test_size=0.6)
X_test, X_val, y_test, y_val = train_test_split(X_test_val, y_test_val, stratify=y, test_size=0.5)
【讨论】:
对我来说更优雅一点的是创建一个随机列,然后按它拆分,这样我们就可以得到一个适合我们需要并且是随机的拆分。
def split_df(df, p=[0.8, 0.2]):
import numpy as np
df["rand"]=np.random.choice(len(p), len(df), p=p)
r = [df[df["rand"]==val] for val in df["rand"].unique()]
return r
【讨论】:
import pandas as pd
from sklearn.model_selection import train_test_split
datafile_name = 'path_to_data_file'
data = pd.read_csv(datafile_name)
target_attribute = data['column_name']
X_train, X_test, y_train, y_test = train_test_split(data, target_attribute, test_size=0.8)
【讨论】:
您可以使用以下代码来创建测试和训练样本:
from sklearn.model_selection import train_test_split
trainingSet, testSet = train_test_split(df, test_size=0.2)
测试大小可能会有所不同,具体取决于您要放入测试和训练数据集中的数据百分比。
【讨论】:
如果您需要根据数据集中的标签列拆分数据,您可以使用:
def split_to_train_test(df, label_column, train_frac=0.8):
train_df, test_df = pd.DataFrame(), pd.DataFrame()
labels = df[label_column].unique()
for lbl in labels:
lbl_df = df[df[label_column] == lbl]
lbl_train_df = lbl_df.sample(frac=train_frac)
lbl_test_df = lbl_df.drop(lbl_train_df.index)
print '\n%s:\n---------\ntotal:%d\ntrain_df:%d\ntest_df:%d' % (lbl, len(lbl_df), len(lbl_train_df), len(lbl_test_df))
train_df = train_df.append(lbl_train_df)
test_df = test_df.append(lbl_test_df)
return train_df, test_df
并使用它:
train, test = split_to_train_test(data, 'class', 0.7)
如果你想控制分裂随机性或使用一些全局随机种子,你也可以传递 random_state。
【讨论】:
像这样从df中选择范围行
row_count = df.shape[0]
split_point = int(row_count*1/5)
test_data, train_data = df[:split_point], df[split_point:]
【讨论】:
df,sn-p 是(或应该是)改组它会改善答案。
有很多有效的答案。添加一个到一堆。 从 sklearn.cross_validation 导入 train_test_split
#gets a random 80% of the entire set
X_train = X.sample(frac=0.8, random_state=1)
#gets the left out portion of the dataset
X_test = X.loc[~df_model.index.isin(X_train.index)]
【讨论】:
这个怎么样? df 是我的数据框
total_size=len(df)
train_size=math.floor(0.66*total_size) (2/3 part of my dataset)
#training dataset
train=df.head(train_size)
#test dataset
test=df.tail(len(df) -train_size)
【讨论】:
您可以利用 df.as_matrix() 函数创建 Numpy-array 并传递它。
Y = df.pop()
X = df.as_matrix()
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size = 0.2)
model.fit(x_train, y_train)
model.test(x_test)
【讨论】:
如果您想稍后添加列,我认为您还需要获取副本而不是数据框切片。
msk = np.random.rand(len(df)) < 0.8
train, test = df[msk].copy(deep = True), df[~msk].copy(deep = True)
【讨论】:
如果您希望输入一个数据帧并输出两个数据帧(不是 numpy 数组),这应该可以解决问题:
def split_data(df, train_perc = 0.8):
df['train'] = np.random.rand(len(df)) < train_perc
train = df[df.train == 1]
test = df[df.train == 0]
split_data ={'train': train, 'test': test}
return split_data
【讨论】:
这是我需要拆分 DataFrame 时写的。我考虑过使用上面 Andy 的方法,但不喜欢我无法精确控制数据集的大小(即有时是 79,有时是 81,等等)。
def make_sets(data_df, test_portion):
import random as rnd
tot_ix = range(len(data_df))
test_ix = sort(rnd.sample(tot_ix, int(test_portion * len(data_df))))
train_ix = list(set(tot_ix) ^ set(test_ix))
test_df = data_df.ix[test_ix]
train_df = data_df.ix[train_ix]
return train_df, test_df
train_df, test_df = make_sets(data_df, 0.2)
test_df.head()
【讨论】:
您也可以考虑将训练集和测试集分层划分。 Startified Division 也随机生成训练和测试集,但以保留原始类比例的方式。这使得训练和测试集更好地反映了原始数据集的属性。
import numpy as np
def get_train_test_inds(y,train_proportion=0.7):
'''Generates indices, making random stratified split into training set and testing sets
with proportions train_proportion and (1-train_proportion) of initial sample.
y is any iterable indicating classes of each observation in the sample.
Initial proportions of classes inside training and
testing sets are preserved (stratified sampling).
'''
y=np.array(y)
train_inds = np.zeros(len(y),dtype=bool)
test_inds = np.zeros(len(y),dtype=bool)
values = np.unique(y)
for value in values:
value_inds = np.nonzero(y==value)[0]
np.random.shuffle(value_inds)
n = int(train_proportion*len(value_inds))
train_inds[value_inds[:n]]=True
test_inds[value_inds[n:]]=True
return train_inds,test_inds
df[train_inds] 和 df[test_inds] 为您提供原始 DataFrame df 的训练和测试集。
【讨论】:
我只会使用 numpy 的 randn:
In [11]: df = pd.DataFrame(np.random.randn(100, 2))
In [12]: msk = np.random.rand(len(df)) < 0.8
In [13]: train = df[msk]
In [14]: test = df[~msk]
只是为了看看这是否有效:
In [15]: len(test)
Out[15]: 21
In [16]: len(train)
Out[16]: 79
【讨论】:
msk 的dtype 为bool、df[msk]、df.iloc[msk] 和df.loc[msk] 总是返回相同的结果。
rand 到 < 0.8 是有意义的,因为它返回 0 到 1 之间的均匀分布的随机数。
in[12]、in[13]、in[14] 行中到底发生了什么吗?我想在这里了解python代码本身
np.random.rand(len(df)) 是一个大小为 len(df) 的数组,浮点值在 [0, 1] 范围内随机均匀分布。 < 0.8 按元素应用比较并将结果存储在适当的位置。因此,值 True,值 >= 0.8 变为 False