Я вижу как минимум две проблемы в коде, который вы разместили. Во-первых, в функции return
остановит оценку функции, как только она будет нажата. Это означает, что вы не собираетесь возвращать выборку для каждой категории, а только выбираете первую (под) категорию и затем полностью выходите из функции. Во-вторых, порядок ваших условий if означает, что среднее условие никогда не может быть запущено, и оба маленьких и больших кадра данных (<1500 или> = 15000 строк) будут обрабатываться этим третьим условием.
Вот функция, которая, я думаю, должна делать то, что вы хотите. Во-первых, я делаю тест категории / подкатегории, чтобы определить, какой столбец использовать (и, как следствие, устранить много повторяющегося кода) и получить (под) категории соответствующим образом. Во-вторых, я создаю пустой фрейм данных для хранения результатов. L oop добавит к этому различные подвыборки. Обратите внимание, что это не эффективный в вычислительном отношении способ сделать это, но это не должно быть проблемой, если ваши фреймы данных не становятся слишком большими. В-третьих, я создаю внутреннюю функцию для выполнения подвыборки. Наконец, я изменил порядок условий if / else. Начинаясь с самого большого и работая вниз, они взаимоисключающие и исчерпывающие все возможности. Обратите внимание, что последнее условие для, если у вас <1500 строк. В этом случае код ничего не вернет (или, точнее, функция вернет пустой фрейм данных). В вашем вопросе не указано, как вы хотите к этому относиться, поэтому пока он просто содержит <code>pass в качестве заполнителя.
def sample_per(df):
# Conditionally set column name and categories variable
if df['Subcategory'].isnull().all():
col_name = 'Subcategory'
else:
col_name = 'Category'
# Get unique (sub)categories
categories = df[col_name].unique()
# Create an empty dataframe to store results
sample_df = pd.DataFrame()
# Create an internal function to do the sampling
def subsample(df, col_name, cat, frac):
return df.loc[(df[col_name] == cat)].apply(lambda x: x.sample(n=2) if x.size*frac < 2 else x.sample(frac=frac))
if df.shape[0] >= 15000:
for cat in categories:
sample_df = sample_df.append(subsample(df, col_name, cat, 0.05))
elif df.shape[0] >= 10000:
for cat in categories:
sample_df = sample_df.append(subsample(df, col_name, cat, 0.03))
elif df.shape[0] >= 1500:
for cat in categories:
sample_df = sample_df.append(subsample(df, col_name, cat, 0.01))
else:
pass
# Return the sampled dataframe
return sample_df
# result of sample_per function
final = sample_per(df2)
Конечно, вы также можете сделать все это, используя groupby
:
def simple_sample(df):
# Conditionally set column name
if df['Subcategory'].isnull().all():
col_name = 'Subcategory'
else:
col_name = 'Category'
def subsample(df, col_name, frac):
return df.groupby(col_name).apply(lambda x: x.sample(n=2) if x.size*frac < 2 else x.sample(frac=frac))
if df.shape[0] >= 15000:
return subsample(df, col_name, 0.05)
elif df.shape[0] >= 10000:
return subsample(df, col_name, 0.03)
elif df.shape[0] >= 1500:
return subsample(df, col_name, 0.01)
else:
return None