Объединение и изменение формы строк и столбцов двух информационных фреймов в R или Python - PullRequest
0 голосов
/ 13 декабря 2018

Есть две таблицы - Таблица A и Таблица B:

Таблица A: Атрибуты продукта Эта таблица содержит два столбца;первый - это уникальный идентификатор продукта, представленный целым числом, второй - строка, содержащая набор атрибутов, назначенных этому продукту.

|---------------------|-----------------------|
|      product        |       tags            |
|---------------------|-----------------------|
|          100        | chocolate, sprinkles  |
|---------------------|-----------------------|
|          101        | chocolate, filled     |
|---------------------|-----------------------|
|          102        | glazed                |
|---------------------|-----------------------|

Таблица B: Атрибуты клиента Вторая таблица также содержит два столбца;первая - строка, содержащая имя клиента, вторая - целое число, содержащее номер продукта.Идентификаторы продукта из второго столбца совпадают с идентификаторами продуктов из первого столбца таблицы A.

customer    product
A           100
A           101
B           101
C           100
C           102
B           101
A           100
C           102

Вам предлагается создать таблицу, соответствующую этому формату, где содержимое ячеек представляет количествопоявление атрибута продукта по клиенту.

customer    chocolate   sprinkles   filled  glazed
A               ?           ?         ?        ?
B               ?           ?         ?        ?
C               ?           ?         ?        ?

Кто-нибудь может мне помочь решить эту проблему в R или Python?

Ответы [ 3 ]

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

В Python:

import pandas as pd

# Creating dataframe for Table A
tableA = [(100, 'chocolate, sprinkles'), (101, 'chocolate, filled'), (102, 'glazed')]
labels = ['product', 'tags']
df_A = pd.DataFrame.from_records(tableA, columns=labels)

# Creating dataframe for Table B
tableB = [('A', 100), ('A', 101), ('B', 101),  ('C', 100), ('C', 102), ('B', 101), ('A', 100), ('C', 102)]
labels = ['customer', 'product']
df_B = pd.DataFrame.from_records(tableB, columns=labels)

new_df = pd.merge(df_A, df_B, how='inner', on='product')
new_df = (new_df.set_index(new_df.columns.drop('tags', 1)
                        .tolist()).tags.str.split(', ', expand=True).stack().reset_index()
           .rename(columns={0: 'tags'}).loc[:, new_df.columns])

final_df = new_df.pivot_table(values='tags', index=['customer'], columns=['tags'],
                      aggfunc='size')
final_df.fillna(0, inplace=True)
final_df = final_df.astype(int)

print(final_df)

Вывод:

tags      chocolate  filled  glazed  sprinkles
customer                                      
   A          3       1       0          2
   B          2       2       0          0
   C          1       0       2          1

Использование R:

library(tidyr)
library(dplyr)
library(reshape2)
library(data.table) ## or library(reshape2)

#Creating the tables
tableA <- data.frame("product" = c(100, 101, 102),
                 "tags" = c("chocolate, sprinkles", "chocolate, filled", "glazed"))
newA = separate_rows(tableA, "tags")

tableB <- data.frame("customer" = c('A', 'A', 'B', 'C', 'C', 'B', 'A', 'C'),
                 "product" = c(100, 101, 101, 100, 102, 101, 100, 102))

joinData = merge(newA, tableB, by=c('product'))

final_df = dcast(melt(as.data.table(joinData), id.vars = c("tags", "customer")), 
             customer ~ tags, value.var = "value")
final_df

Вывод:

> final_dfcena
   customer chocolate filled glazed sprinkles
1:        A         3      1      0         2
2:        B         2      2      0         0
3:        C         1      0      2         1
0 голосов
/ 13 декабря 2018

Метод python можно существенно упростить, используя встроенные методы для получения фиктивных переменных.Затем merge, за которым следует groupby + sum.Начиная с данных, предоставленных @ SuryaMurali

import pandas as pd

df_A = pd.concat([df_A, df_A.tags.str.get_dummies(sep=', ')], 1).drop(columns='tags')
df_B.merge(df_A).drop(columns='product').groupby('customer').sum()

Вывод:

           filled   sprinkles  chocolate  glazed
customer                                        
A               1           2          3       0
B               2           0          2       0
C               0           1          1       2
0 голосов
/ 13 декабря 2018

Мы объединяем столбец «product», разделяем «теги» в разделителе, чтобы расширить строки, получаем частоту «тегов», «customer» с count и spread в «широком» формате.

library(tidyverse)
df1 %>% 
   right_join(df2) %>% 
   separate_rows(tags) %>%
   count(tags, customer) %>% 
   spread(tags, n, fill = 0)
# A tibble: 3 x 5
#  customer chocolate filled glazed sprinkles
#  <chr>        <dbl>  <dbl>  <dbl>     <dbl>
#1 A                3      1      0         2
#2 B                2      2      0         0
#3 C                1      0      2         1

данные

df1 <- structure(list(product = 100:102, tags = c("chocolate, sprinkles", 
"chocolate, filled", "glazed")), class = "data.frame", row.names = c(NA, 
 -3L))

df2 <- structure(list(customer = c("A", "A", "B", "C", "C", "B", "A", 
 "C"), product = c(100L, 101L, 101L, 100L, 102L, 101L, 100L, 102L
 )), class = "data.frame", row.names = c(NA, -8L))
...