#python-3.x #pandas
#python-3.x #pandas
Вопрос:
У меня есть столбец dataframe, который выглядит следующим образом (примерно 200 строк):
col1
a
b
c
d
e
f
Я хочу создать новый фрейм данных с одним столбцом и 15 наборами из 3 случайных комбинаций элементов в столбце pandas. например:
new_df
combinations:
(a,b,c)
(a,c,d)
(a,d,c)
(b,a,d)
(d,a,c)
(a,d,f)
(e,a,f)
(a,f,e)
(b,e,f)
(f,b,e)
(c,b,e)
(b,e,a)
(a,e,f)
(e,f,a)
В настоящее время код, который у меня есть, создает комбинацию всех возможных комбинаций и исчерпывает память, когда я пытаюсь добавить результаты в другой фрейм данных:
import pandas as pd
from itertools import permutations
df = pd.read_csv('')
combo = df['col1'].tolist()
perm = permutations(combo,3)
combinations = pd.DataFrame(columns=['combinations'])
list_ = []
for i in list(perm):
combinations['combinations'] = i
list_.append(i)
Как мне остановить наборы случайных комбинаций, чтобы остановиться на любом X количестве наборов или, в данном случае, 15 комбинациях из 3?
Комментарии:
1. @anon01 повторной выборки, если это возможно, не требуется.
2. вам нужны перечислимые комбинации или случайные комбинации?
3. @anon01 случайное — это то, что я хочу
4. вы также говорите комбинации, но показываете перестановки. Что это?
5. @anon01 комбинации. Меня не волнует порядок.
Ответ №1:
Причина, по которой вашему коду не хватает памяти, заключается именно в той части, в которой вы вызываете list(perm)
. выполнение этого приведет к созданию ВСЕХ возможных перестановок. Поэтому, когда вы делаете
for i in list(perm):
...
Вы говорите python создать список всех перестановок, а затем попытаться выполнить итерацию по этому списку. Вместо этого, если вы выполняете итерацию по тому generator
, что permutations
создает вызов (например for i in perm:
, вместо for i in list(perm):
), вы можете просто выполнить итерацию по каждой перестановке, не сохраняя их все сразу в памяти. Итак, если вы прервете цикл for после того, как он повторится 15 раз, вы сможете достичь желаемого результата.
Однако, поскольку мы используем itertools
, мы можем значительно упростить эту логику, используя islice
для выполнения работы по получению первых 15 без явного написания for-loop
и прерывания на 15-й итерации:
import pandas as pd
from itertools import permutations, islice
# df = pd.read_csv('')
# combo = df['col1'].tolist()
combo = list("abcefg")
perm_generator = permutations(combo,3)
# get first 15 permutations without running the generator
first_15_perms = islice(perm_generator, 15)
# Store the first 15 permutations into a Series object
series_perms = pd.Series(list(first_15_perms), name="permutations")
print(series_perms)
0 (a, b, c)
1 (a, b, e)
2 (a, b, f)
3 (a, b, g)
4 (a, c, b)
5 (a, c, e)
6 (a, c, f)
7 (a, c, g)
8 (a, e, b)
9 (a, e, c)
10 (a, e, f)
11 (a, e, g)
12 (a, f, b)
13 (a, f, c)
14 (a, f, e)
Name: permutations, dtype: object
Если вы хотите, чтобы это было как один столбец в a DataFrame
, вы можете использовать to_frame()
метод:
df_perms = series_perms.to_frame()
print(df_perms)
permutations
0 (a, b, c)
1 (a, b, e)
2 (a, b, f)
3 (a, b, g)
4 (a, c, b)
5 (a, c, e)
6 (a, c, f)
7 (a, c, g)
8 (a, e, b)
9 (a, e, c)
10 (a, e, f)
11 (a, e, g)
12 (a, f, b)
13 (a, f, c)
14 (a, f, e)
Комментарии:
1. Ваше объяснение очень полезно. Однако, когда я запускаю
series_perms = pd.Series(first_15_perms, name="permutations")
, я получаю сообщение об ошибкеTypeError: object of type 'itertools.islice' has no len()
. Я пытаюсь исправить это сейчас2. Вы можете создать временный список. Вероятно, это функция в новой версии pandas, которая позволяет генератору в
Series
. Попробуйте:pd.Series(list(first_15_perms), name="permutations")
3. Я думал, вас интересует случайная последовательность
Ответ №2:
Хотя это и не так элегантно, как предыдущие ответы, если вы действительно хотите создать случайную выборку значений, а не только первое, вы также можете сделать что-то вроде следующего:
def newFrame(df: pd.DataFrame, srccol: int, cmbs: int, rows: int) -> pd.DataFrame:
il = df[srccol].values.tolist()
nw_df = pd.DataFrame()
data = []
for r in range(rows):
rd =[]
for ri in range(cmbs):
rd.append(rnd.choice(il))
data.append(tuple(rd))
nw_df['Combinations'] = data
return nw_df
Который при передаче a a df, как показано в вашем примере, в виде:
new_df = newFrame(df, 0, 3, 15)
Производит:
Combinations
0 (a, f, e)
1 (a, d, f)
2 (b, c, d)
3 (a, a, d)
4 (f, b, c)
5 (e, b, b)
6 (e, e, d)
7 (c, f, f)
8 (f, e, b)
9 (d, c, e)
Комментарии:
1. Эй, просто хотел поблагодарить вас, но я выбрал вышеупомянутое решение