#python-3.x #pandas #dataframe
Вопрос:
Я новичок в python, и у меня есть фрейм данных pandas, который является результатом добавления нескольких сущностей. Ниже приведен пример фрейма данных (он может быть больше этого):
main_tag | метка | ценность |
---|---|---|
генеид | генеид | 121175336 |
Статус | Статус | ЖИВЫЕ КОНЦЕРТЫ |
дата создания | Дата-std_year | 2017 |
дата создания | Дата-начало месяца | 4 |
дата создания | Дата-std_day | 0 |
дата обновления | Дата-std_year | 2021 |
дата обновления | Дата-начало месяца | 3 |
дата обновления | Дата-std_day | 21 |
Org-ref_taxname | Org-ref_taxname | Gmax |
Org-ref_db | Dbtag_db | таксон1 |
Org-ref_db | Объект-id_id | 3845 |
OrgName_div | OrgName_div | PLN |
генеид | генеид | 121175335 |
Статус | Статус | ЖИВЫЕ КОНЦЕРТЫ |
дата создания | Дата-std_year | 2011 |
дата создания | Дата-начало месяца | 4 |
дата создания | Дата-std_day | 20 |
дата обновления | Дата-std_year | 2021 |
дата обновления | Дата-начало месяца | 4 |
дата обновления | Дата-std_day | 21 |
Org-ref_taxname | Org-ref_taxname | Глицин |
Org-ref_db | Dbtag_db | таксон2 |
Org-ref_db | Объект-id_id | 3847 |
OrgName_div | OrgName_div | LSA |
генеид | генеид | 121175334 |
Статус | Статус | ЖИВЫЕ КОНЦЕРТЫ |
дата создания | Дата-std_year | 2011 |
дата создания | Дата-начало месяца | 6 |
дата создания | Дата-std_day | 20 |
update-date | Date-std_year | 2018 |
update-date | Date-std_month | 8 |
update-date | Date-std_day | 21 |
Org-ref_taxname | Org-ref_taxname | GlycineMin |
Org-ref_db | Dbtag_db | taxon3 |
Org-ref_db | Object-id_id | 38467 |
OrgName_div | OrgName_div | PLN |
As tables shows, the sub-dataframe from «geneid» to «OrgName_div» is been repeated with different values and I need the fastest way to transpose and change it to something like this:
geneid | status | create-date | update-date | Org-ref_taxname | Org-ref_db | Org-ref_db | OrgName_div |
---|---|---|---|---|---|---|---|
121175336 | ЖИВЫЕ КОНЦЕРТЫ | 2017-4-2 | 2021-3-21 | Gmax | таксон1 | 3845 | PLN |
121175335 | ЖИВЫЕ КОНЦЕРТЫ | 2011-4-20 | 2021-4-21 | Глицин | таксон2 | 3847 | LSA |
121175334 | ЖИВЫЕ КОНЦЕРТЫ | 2011-6-20 | 2018-8-21 | ГлицинеМин | таксон3 | 38467 | PLN |
Вот код, который генерирует этот фрейм данных, который в основном анализирует огромный xml-файл:
import numpy as np import pandas as pd from lxml import etree class EntrezGene: def __init__(self, fh,tg): self.context = etree.iterparse(fh, events=("end",),tag=tg,huge_tree=True) def _parse(self): for event, elem in self.context: yield elem elem.clear() while elem.getprevious() is not None: del elem.getparent()[0] def sequence(self, elements): _elements = {}#[] for elem in elements: if len(elem): _elements[elem.tag]= dict(self.sequence(elem)) else: _elements[elem.tag] =elem.text return _elements def __iter__(self): for xml_EntrezGene in self._parse(): if len(xml_EntrezGene.attrib): EntrezGene = {xml_EntrezGene.tag: xml_EntrezGene.attrib[next(iter(xml_EntrezGene.attrib))]} #xml_EntrezGene.attrib mainTag = xml_EntrezGene.tag elif len(xml_EntrezGene.text.strip()):#len(xml_EntrezGene.text) : EntrezGene = {xml_EntrezGene.tag: xml_EntrezGene.text} mainTag = xml_EntrezGene.tag else: EntrezGene = {} mainTag = xml_EntrezGene.tag for elem in xml_EntrezGene: # if elem is Sequence if len(elem): # Append tuple(tag, value) EntrezGene[elem.tag] = self.sequence(elem) mainTag = elem.getparent().tag else: EntrezGene[elem.tag] = elem.text mainTag = elem.getparent().tag yield EntrezGene, mainTag def recursive_items(dictionary): for key, value in dictionary.items(): if type(value) is dict: #print(key) yield from recursive_items(value) else: yield (key, value) poTags =['geneid','status','OrgName_div','Org-ref_db','Org-ref_taxname','create-date', 'update-date'] def extract_xml_inf(xmlFileName, tagNames): df = pd.DataFrame(columns=['main_tag','tag', 'value']) with open(xmlFileName, 'rb') as in_xml: for record in EntrezGene(in_xml,tg=tagNames): for key, value in record[0].items(): if isinstance(value, (dict)): for subKey, subValue in recursive_items(value): df = df.append({'main_tag': record[1],'tag': subKey,'value': subValue}, ignore_index=True) else: df = df.append({'main_tag': record[1],'tag': key,'value': value}, ignore_index=True) #print(df) return df
Я ценю любую помощь.
Комментарии:
1.
df.assign(id = (df.main_tag == 'geneid').cumsum()).groupby(['id', 'main_tag']).aggregate({'value':'-'.join}).unstack()
Ответ №1:
Вы могли бы сделать:
df1 = df.assign(id = (df.main_tag == 'geneid').cumsum()). groupby(['id', 'main_tag']).aggregate({'value':'-'.join}).reset_index(). pivot('id', 'main_tag', 'value')[df.main_tag.unique()] print(df1) main_tag geneid status create-date update-date Org-ref_taxname Org-ref_db OrgName_div id 1 121175336 live 2017-4-0 2021-3-21 Gmax taxon1-3845 PLN 2 121175335 live 2011-4-20 2021-4-21 Glycine taxon2-3847 LSA 3 121175334 live 2011-6-20 2018-8-21 GlycineMin taxon3-38467 PLN
Ответ №2:
Возможно, вы можете с самого начала подойти к этому по-другому. Если вам нужно все добавить, а затем изменить, у кого-то другого может быть решение для вас.
Перед объединением перенесите только столбцы значений, а затем объедините их. Затем вы можете внести изменения в даты. У меня нет вашего кода, используемого для объединения ваших данных, поэтому вам придется изменить это заявление по мере необходимости.
# hold individual df in a list df_hold =[] for i in range(3): # .T for transpose df_hold.append(df[['value']].T) df = pd.concat(df_hold) # note the _c in some of the dates to remove the chance of duplicate column names tags = ['geneid', 'status', 'Date-std_year_c', 'Date-std_month_c', 'Date-std_day_c', 'Date-std_year', 'Date-std_month', 'Date-std_day', 'Org-ref_taxname', 'Dbtag_db', 'Object-id_id', 'OrgName_div'] df.columns = tags df['create-date'] = df.apply(lambda x: '-'.join([x['Date-std_year_c'], x['Date-std_month_c'], x['Date-std_day_c']]), axis=1) df['update-date'] = df.apply(lambda x: '-'.join([x['Date-std_year'], x['Date-std_month'], x['Date-std_day']]), axis=1) # drop unwanted columns df = df.drop(['Date-std_year_c', 'Date-std_month_c', 'Date-std_day_c', 'Date-std_year', 'Date-std_month', 'Date-std_day'], axis=1).set_index('geneid', drop=True)
это просто запуск первого генеида три раза, поэтому данные одинаковы в каждой строке
status Org-ref_taxname Dbtag_db Object-id_id OrgName_div create-date update-date geneid 121175336 live Gmax taxon1 3845 PLN 2017-4-0 2021-3-21 121175336 live Gmax taxon1 3845 PLN 2017-4-0 2021-3-21 121175336 live Gmax taxon1 3845 PLN 2017-4-0 2021-3-21