Объединение двух pandas фреймов данных с общими значениями, которые представлены в одном фрейме данных в виде столбцов, а в другом - в строках - PullRequest
1 голос
/ 02 марта 2020

У меня есть один кадр данных, который содержит сотни столбцов в качестве идентификатора клиента и одну строку с общим количеством заявок на идентификатор клиента, это выглядит так: (df1 является результатом нескольких преобразований исходного файла CSV)

df1
+-----+----+-----+
| 30  | 5  | 100 |
+-----+----+-----+
| 122 | 40 |  13 |
+-----+----+-----+

И еще один кадр данных, который имеет 2 столбца, один account_id и client_id, выглядит следующим образом:

df2
+------------+-----------+
| account_id | client_id |
+------------+-----------+
| 4char      | 4         |
+------------+-----------+
| 3char      | 5         |
+------------+-----------+
| 2char      | 30        |
+------------+-----------+
| 16char     | 9         |
+------------+-----------+
| 17char     | 100       |
+------------+-----------+

Я хочу иметь один файл, который содержит 3 столбца account_id, client_id и total_tickets, который будет выглядеть так:

df
+------------+-----------+---------------+
| account_id | client_id | total_tickets |
+------------+-----------+---------------+
| 4char      | 4         | null
+------------+-----------+---------------+
| 3char      | 5         | 40
+------------+-----------+---------------+
| 2char      | 30        | 122
+------------+-----------+---------------+
| 16char     | 9         | null
+------------+-----------+---------------+
| 17char     | 100       | 13
+------------+-----------+---------------+

До сих пор я достиг этого момента: я создал функцию iterrows () на обоих фреймах данных, проверьте с помощью функции isin (), найден ли client_id в df2 в столбцы df1, затем я добавляю новый столбец total_tickets с функцией assign () на df2

f1 = df1, f2 = df2
def populating_df(f1, f2):
    for org_nr in f2.iterrows():
        for col in f1.iterrows():
           matched_org_nr =  f2.client_id.isin(f1.columns)
           if matched_org_nr.any() == True:
               sum_of_tickets_per_col = matched_org_nr
           # create a new column in f2 file with the values of total_tickets for each org number matched
           f2 = f2.loc[:].assign(Total_Tickets=sum_of_tickets_per_col) 
        return f2

и получаю в результате эту таблицу:

+------------+-----------+---------------+
| account_id | client_id | total_tickets |
+------------+-----------+---------------+
|  4char     | 4         |False
+------------+-----------+---------------+
|  3char     | 5         | True
+------------+-----------+---------------+
|  2char     | 30        | True
+------------+-----------+---------------+
| 16char     | 9         | False
+------------+-----------+---------------+
| 17char     | 100       | True
+------------+-----------+---------------+

Я был бы счастлив если у кого-нибудь есть предложения по решению этой проблемы

Ответы [ 3 ]

1 голос
/ 02 марта 2020

Сначала нам нужно расплавить df1, чтобы у вас было наблюдение для каждой строки

, затем вы можете объединить, используя external, чтобы получить ключи из обоих столбцов

df_melt = pd.melt(df1,var_name='client_id',value_name='total_tickets')

df3 = pd.merge(df_melt ,df2,on=['client_id'],how='outer')

#make sure dtypes are the same.

#df_melt ['client_id'] = df_melt ['client_id'].astype(int) 

df3 = df3[["account_id", "client_id", "total_tickets"]].sort_values(
    "account_id", ascending=False
)

print(df3)

     account_id  client_id  total_tickets
3   4char                4            NaN
1   3char                5           40.0
0   2char               30          122.0
2   17char             100           13.0
4   16char               9            NaN
1 голос
/ 02 марта 2020

merge является ключом, но вы должны сначала транспонировать начальный фрейм данных и внести некоторые косметические c изменения, такие как сброс его индекса и предоставление соответствующих имен столбцов:

Преобразование может быть :

df1.rename({0: 'total_tickets'}).T.rename_axis('client_id').reset_index()

предоставление:

   client_index  total_tickets
0            30            122
1             5             40
2           100             13

После того, как это будет сделано, объединение будет тривиальным:

result = df2.merge(df1.rename({0: 'total_tickets'}).T.rename_axis('client_id').reset_index(),
                   on='client_id', how='left')

, что дает ожидаемый результат:

  account_id  client_id  total_tickets
0      4char          4            NaN
1      3char          5           40.0
2      2char         30          122.0
3     16char          9            NaN
4     17char        100           13.0
0 голосов
/ 02 марта 2020

Вы можете использовать pd.merge.

df = pd.merge(df1, df2, on="client_id", how='outer')
...