Python панды, чтобы гарантировать, что каждая строка на основе значения столбца имеет набор данных, если не добавить строку - PullRequest
0 голосов
/ 08 октября 2019

Я организовываю ресурсы AWS для тегирования и собираю данные в файл CSV. Пример вывода файла CSV выглядит следующим образом. Я пытаюсь убедиться, что для каждого resource_id есть набор данных tag_key, который мне нужно обеспечить. Этот набор данных

tag_key

Application
Client
Environment
Name
Owner
Project
Purpose

Я новичок в пандах, мне только удалось получить файл CSV, прочитанный как фрейм данных

import pandas as pd

file_name = "z.csv"

df = pd.read_csv(file_name, names=['resource_id', 'resource_type', 'tag_key', 'tag_value'])

print (df)

CSVфайл

vol-00441b671ca48ba41,volume,Environment,Development
vol-00441b671ca48ba41,volume,Name,Database Files
vol-00441b671ca48ba41,volume,Project,Application Development
vol-00441b671ca48ba41,volume,Purpose,Web Server
i-1234567890abcdef0,instance,Environment,Production
i-1234567890abcdef0,instance,Owner,Fast Company

Я ожидаю, что результат будет следующим:

vol-00441b671ca48ba41,volume,Environment,Development
vol-00441b671ca48ba41,volume,Name,Database Files
vol-00441b671ca48ba41,volume,Project,Application Development
vol-00441b671ca48ba41,volume,Purpose,Web Server
vol-00441b671ca48ba41,volume,Client,
vol-00441b671ca48ba41,volume,Owner,
vol-00441b671ca48ba41,volume,Application,
i-1234567890abcdef0,instance,Environment,Production
i-1234567890abcdef0,instance,Owner,Fast Company
i-1234567890abcdef0,instance,Application,
i-1234567890abcdef0,instance,Client,
i-1234567890abcdef0,instance,Name,
i-1234567890abcdef0,instance,Project,
i-1234567890abcdef0,instance,Purpose,

Ответы [ 2 ]

0 голосов
/ 08 октября 2019

Один из способов сделать это - использовать мультииндексы from_product и renindex:

taglist = ['Application',
           'Client',
           'Environment',
           'Name',
           'Owner',
           'Project',
           'Purpose']

df_out = df.set_index(['resource_id','tag_key'])\
           .reindex(pd.MultiIndex.from_product([df['resource_id'].unique(), taglist],
                                              names=['resource_id','tag_key']))

df_out.assign(resource_type = df_out.groupby('resource_id')['resource_type']\
                                    .ffill().bfill()).reset_index()

Вывод:

              resource_id      tag_key resource_type                tag_value
0   vol-00441b671ca48ba41  Application        volume                      NaN
1   vol-00441b671ca48ba41       Client        volume                      NaN
2   vol-00441b671ca48ba41  Environment        volume              Development
3   vol-00441b671ca48ba41         Name        volume           Database Files
4   vol-00441b671ca48ba41        Owner        volume                      NaN
5   vol-00441b671ca48ba41      Project        volume  Application Development
6   vol-00441b671ca48ba41      Purpose        volume               Web Server
7     i-1234567890abcdef0  Application      instance                      NaN
8     i-1234567890abcdef0       Client      instance                      NaN
9     i-1234567890abcdef0  Environment      instance               Production
10    i-1234567890abcdef0         Name      instance                      NaN
11    i-1234567890abcdef0        Owner      instance             Fast Company
12    i-1234567890abcdef0      Project      instance                      NaN
13    i-1234567890abcdef0      Purpose      instance                      NaN
0 голосов
/ 08 октября 2019

Чтобы сделать немного более простой пример. У меня есть датафрейм df:

df = pd.DataFrame(data={'a': [1, 1, 2, 2], 'b': [[1, 2], [3, 5], [1, 2], [5]]})

Возвращается

   a       b
0  1  [1, 2]
1  1  [3, 5]
2  2  [1, 2]
3  2     [5]

С необходимыми б: 1, 2, 3, 4 и 5.

Тогда нам нужно выяснитьчто у нас «уже есть». Это мы делаем:

def flatten(lsts):
    return [j for i in lsts for j in i]

df_new = df.groupby(by=['a'])['b'].apply(flatten)

Возвращает:

a
1    [1, 2, 3, 5]
2       [1, 2, 5]

Теперь нам нужно перечислить отсутствующие столбцы и добавить их:

df_new = df_new.reset_index()
lst_wanted = [1, 2, 3, 4, 5]

for row in df_new.itertuples():
    for j in lst_wanted:
        if j not in row.b:
            df = df.append({'a': row.a, 'b': j}, ignore_index=True)
print(df)

Возвращение:

   a       b
0  1  [1, 2]
1  1  [3, 5]
2  2  [1, 2]
3  2     [5]
4  1       4
5  2       3
6  2       4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...