Создайте DataFrame, который состоит из всех пар строк из другого - PullRequest
1 голос
/ 05 февраля 2020

У меня есть DF, который имеет две колонки: вопросы и ответы. Колонка ответов содержит дубликаты.

Теперь я хотел бы создать новый DF, который имеет три столбца: вопрос1, вопрос2, дубликат.

Столбцы вопрос1 и вопрос2 будут заполняться как каждая уникальная комбинация всех вопросов в исходном DF. Дублирующий столбец будет иметь логическое значение, соответствующее тому, имеют ли вопросы одинаковый ответ в начальном DF.

Начальный DF составляет ~ 13 000 строк, и поэтому результирующий DF будет большим (я полагаю, слишком большой для Pandas на моей машине, но я могу уменьшить начальный DF для тестирования и затем изменить его на что-то, отличное от pandas, если мне нужны все данные).

Есть ли способ это сделать в любом случае быстрее, чем вложенное в O (N ^ 2) l oop, так как это занимает слишком много времени без распараллеливания / векторизации:

questions1, questions2, duplicates = [], [], []

for i in range(len(dataset)-1):
    print(f'{i+1} / {len(dataset)-1}')
    question1 = dataset.iloc[i]['question']
    answer1 = dataset.iloc[i]['answer']
    for j in range(i+1, len(dataset)):
        question2 = dataset.iloc[j]['question']
        answer2 = dataset.iloc[j]['answer']
        duplicate = answer1 == answer2
        questions1.append(question1)
        questions2.append(question2)
        duplicates.append(duplicate)

duplicate_dataset = pd.DataFrame({
    'question1': questions1,
    'question2': questions2,
    'duplicate': duplicates
})

РЕДАКТИРОВАТЬ: В соответствии с запросом, вот игрушечный образец ввода DF:

df = pd.DataFrame({
    'question': ['abc', 'def', 'ghi', 'jkl', 'mno', 'pqr', 'stu', 'vwx', 'yzz'],
    'answer': ['1', '2', '1', '3', '4', '4', '5', '1', '6']
})

И результирующий DF должен быть равен этому:

df2 = pd.DataFrame({
    'question1': [
        'abc', 'abc', 'abc', 'abc',
        'abc', 'abc', 'abc', 'abc',
        'def', 'def', 'def', 'def',
        'def', 'def', 'def', 'ghi',
        'ghi', 'ghi', 'ghi', 'ghi',
        'ghi', 'jkl', 'jkl', 'jkl',
        'jkl', 'jkl', 'mno', 'mno',
        'mno', 'mno', 'pqr', 'pqr',
        'pqr', 'stu', 'stu', 'vwx'
    ],
    'question2': [
        'def', 'ghi', 'jkl', 'mno',
        'pqr', 'stu', 'vwx', 'yzz',
        'ghi', 'jkl', 'mno', 'pqr',
        'stu', 'vwx', 'yzz', 'jkl',
        'mno', 'pqr', 'stu', 'vwx',
        'yzz', 'mno', 'pqr', 'stu',
        'vwx', 'yzz', 'pqr', 'stu',
        'vwx', 'yzz', 'stu', 'vwx',
        'yzz', 'vwx', 'yzz', 'yzz'
    ],
    'duplicate': [
        False, True, False, False,
        False, False, True, False,
        False, False, False, False,
        False, False, False, False,
        False, False, False, True,
        False, False, False, False,
        False, False, True, False,
        False, False, False, False,
        False, False, False, False
    ]
})

Ответы [ 2 ]

2 голосов
/ 05 февраля 2020

Вот еще одно решение, которое по-прежнему опирается на itertools.combinsk и zip .

Объедините df.question и df.answer, используйте комбинации для создания неповторяющихся пар, используйте понимание списка, чтобы получить пары True или False и, наконец, создайте новый кадр данных с выходными данными.

from itertools import combinations
#zip columns, then combine
M = (combinations(zip(df.question,df.answer),2))

#list comprehension here to get ur True or False entries
outcome = [(i[0],j[0],True) 
            if i[-1]==j[-1] else (i[0],j[0],False) 
            for i, j in M]

 #create new dataframe
new_df = pd.DataFrame(outcome,columns= ['question1','question2','duplicate'])
1 голос
/ 05 февраля 2020

Вот один из способов использования itertools.combinations и Series.map:

from itertools import combinations

# Create mapping Series of questions - answers
q_map = df.drop_duplicates(subset='question').set_index('question')['answer']

# Create DataFrame of all combinations of questions
df2 = pd.DataFrame(combinations(df['question'].unique(), 2), columns=['question1', 'question2'])

# Create duplicate field using the helper mapping Series
df2['duplicate'] = df2['question1'].map(q_map) == df2['question2'].map(q_map)

[out]

   question1 question2  duplicate
0        abc       def      False
1        abc       ghi       True
2        abc       jkl      False
3        abc       mno      False
4        abc       pqr      False
5        abc       stu      False
6        abc       vwx       True
7        abc       yzz      False
8        def       ghi      False
9        def       jkl      False
10       def       mno      False
11       def       pqr      False
12       def       stu      False
13       def       vwx      False
14       def       yzz      False
15       ghi       jkl      False
16       ghi       mno      False
17       ghi       pqr      False
18       ghi       stu      False
19       ghi       vwx       True
20       ghi       yzz      False
21       jkl       mno      False
22       jkl       pqr      False
23       jkl       stu      False
24       jkl       vwx      False
25       jkl       yzz      False
26       mno       pqr       True
27       mno       stu      False
28       mno       vwx      False
29       mno       yzz      False
30       pqr       stu      False
31       pqr       vwx      False
32       pqr       yzz      False
33       stu       vwx      False
34       stu       yzz      False
35       vwx       yzz      False
...