Кросс-табуляция подсчитывает между парами ключевых слов на группу с пандами - PullRequest
0 голосов
/ 16 декабря 2018

У меня есть таблица с ключевыми словами, связанными со статьями, выглядит так:

article_id  keyword
1           A
1           B
1           C
2           A
2           B
2           D
3           E
3           F
3           D

Мне нужно получить сводную таблицу:

    A   B   C   D   E   F
A   -   2   1   1   0   0
B   -   -   1   1   0   0
C   -   -   -   0   0   0
D   -   -   -   -   1   1
E   -   -   -   -   -   1
F   -   -   -   -   -   -

Это означает, чтопара (A, B) встречается в двух статьях (# 1 и # 2), пара (A, C) встречается только в одной статье (# 1) и т. д.

Какой самый питонский способ сделать это?

Я пробовал сводные таблицы Pandas, но пока безуспешно.Просто не могу понять, как связать ключевые слова и идентификаторы статей.

Этот вопрос Создать матрицу смежности для двух столбцов в панде. не решает проблему.

Ответы [ 3 ]

0 голосов
/ 16 декабря 2018

Вы также можете сделать это, используя merge и crosstab

df_merge = df.merge(df, on='article_id')
pd.crosstab(df_merge['keyword_x'], df_merge['keyword_y'])

или merge и pivot_table

df_merge = df.merge(df, on='article_id')
df_merge.pivot_table('article_id', 'keyword_x', 'keyword_y', 'count', 0)

оба в результате

keyword_y  A  B  C  D  E  F
keyword_x                  
A          2  2  1  1  0  0
B          2  2  1  1  0  0
C          1  1  1  0  0  0
D          1  1  0  2  1  1
E          0  0  0  1  1  1
F          0  0  0  1  1  1
0 голосов
/ 16 декабря 2018

Вы можете использовать product над группами и использовать для циклов для увеличения счетчика, т.е.

from itertools import product 

df2 = pd.DataFrame(columns=df['keyword'].unique(),index=df['keyword'].unique()).fillna(0)


for i in df.groupby('article_id')['keyword'].apply(lambda x : product(x,x)).values:
    for k,l in i:
        if k==l:
            df2.loc[k,l]='-'
        elif df2.loc[k,l]!=0:
            df2.loc[k,l]+=1
        else:
            df2.loc[k,l]=1

df2 = df2.where((df2=='-').cumsum().T.astype(bool),'-')

   A  B  C  D  E  F
A  -  2  1  1  0  0
B  -  -  1  1  0  0
C  -  -  -  0  0  0
D  -  -  -  -  1  1
E  -  -  -  -  -  1
F  -  -  -  -  -  -
0 голосов
/ 16 декабря 2018

Используйте crosstab и dot.Затем вы можете использовать np.triu, чтобы сохранить только верхнюю половину матрицы (все остальное установлено в 0).

u = pd.crosstab(df.article_id, df.keyword)
v = u.T.dot(u)
pd.DataFrame(np.triu(v, k=1), index=v.index.values, columns=v.columns.values)

   A  B  C  D  E  F
A  0  2  1  1  0  0
B  0  0  1  1  0  0
C  0  0  0  0  0  0
D  0  0  0  0  1  1
E  0  0  0  0  0  1
F  0  0  0  0  0  0

В качестве альтернативы, для последнего шага вы можете установить недопустимые значения в«-1», как лучшая альтернатива «-» для недопустимых значений.

v.values[np.tril_indices_from(v)] = -1
print(v)

keyword  A  B  C  D  E  F
keyword                  
A       -1  2  1  1  0  0
B       -1 -1  1  1  0  0
C       -1 -1 -1  0  0  0
D       -1 -1 -1 -1  1  1
E       -1 -1 -1 -1 -1  1
F       -1 -1 -1 -1 -1 -1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...