Извлеките части столбца, содержащие жала, и создайте словари, из которых можно извлечь значения на основе общих ключей

#python #python-3.x #pandas #string #dictionary

Вопрос:

У меня есть df, содержащий строки с несколькими данными, которые я хочу проанализировать и сохранить в виде словаря. Я хотел бы сохранить PubMed Identifier в качестве pmid ключа и следующие цифры в качестве его значений, Embase как euid и следующие цифры, NCT как trialid и следующее число (без пробела), и игнорировать числа самостоятельно или игнорировать PubMed Identifier/Embase без конечных/связанных цифр.

 data = {"ORN": [1, 2, 3, 4],
        "EN": ["PubMed Identifier 27955689", "PubMed Identifier 8010359Embase  24208639", "PubMed Identifier 12237786Embase  35148801", "PubMed Identifier NCT02360007 12537613"]
        }

df = pd.DataFrame(data=data)

    ORN EN
0   1   PubMed Identifier 27955689
1   2   PubMed Identifier 8010359Embase 24208639
2   3   PubMed Identifier 12237786Embase 35148801
3   4   PubMed Identifier NCT02360007 12537613


desired_df

    ORN EN
0   1   {"pmid": 27955689}
1   2   {"pmid":  8010359, "euid": 24208639}
2   3   {"pmid": 12237786, "euid": 35148801}
3   4   {"trialid": 02360007}


 

Я не могу понять, что мне следует делать с наилучшим подходом. Моя идея разделить строку по столбцам, .split(expand=True) а затем изменить порядок столбцов, а затем объединить их обратно с помощью a to_dict() -лучшее, что я могу придумать, но любые лучшие предложения были бы замечательными. Манипуляции со строками-это то, в чем мне нужно совершенствоваться.

Комментарии:

1. извините — мне трудно следить за тем, что вы пытаетесь сделать. Вы пытаетесь построить несколько кадров данных, разделяя их по строкам в зависимости от того, находятся ли «Embase» или » NCT » во втором столбце? или вы пытаетесь проанализировать значения во втором столбце, разделив числа «Embase» и/или «NCT» на новые столбцы? Если бы вы могли показать нам, что вы хотите, чтобы произошло с вашим примером, это было бы действительно полезно. Имейте в виду, что мы не знаем этого набора данных/поля, поэтому единственное, в чем мы можем помочь, — это то, что вы нам расскажете 🙂

2. @MichaelDelgado Последний, хочу проанализировать значения во втором столбце EN и вернуть результаты , показанные сейчас desired_df , спасибо.

3. Почему у ORN 4 нет pmid?

4. @MichaelDelgado, к сожалению, это происходит, без объяснения причин. Это то, что я получаю из своих поисковых запросов по этим библиографическим базам данных.

Ответ №1:

Извлеките данные с помощью .str.extract()

Создайте диктант с .apply() помощью dropna() to_dict() :

  1. Извлеките данные с помощью .str.extract()
 df_extract = df['EN'].str.extract(r'PubMed Identifiers*(?:(?P<pmid>d )(?:Embases*(?P<euid>d ))?)|NCT(?P<trialid>d )')
 

или используйте:

 df_extract = df['EN'].str.extract(r'PubMed Identifiers*(?P<pmid>d )?s*(?:Embases*(?P<euid>d ))?(?:NCTs*(?P<trialid>d ))?')
 

Результат:

 print(df_extract)


       pmid      euid   trialid
0  27955689       NaN       NaN
1   8010359  24208639       NaN
2  12237786  35148801       NaN
3       NaN       NaN  02360007
 
  1. Создайте диктант с .apply() помощью dropna() to_dict() :
 df_extract.apply(lambda x: x.dropna().to_dict(), axis=1)
 

Результат:

 0                        {'pmid': '27955689'}
1     {'pmid': '8010359', 'euid': '24208639'}
2    {'pmid': '12237786', 'euid': '35148801'}
3                     {'trialid': '02360007'}
dtype: object
 

Ответ №2:

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

 d = {'PubMed Identifier': 'pmid',
     'Embase': 'emid', 'NCT': 'trialid'}

pat = fr'({"|".join(d)})s*(d )'
df['EN'].str.findall(pat).map(lambda l: {d[k]: v for k, v in l})
 

 0                        {'pmid': '27955689'}
1     {'pmid': '8010359', 'emid': '24208639'}
2    {'pmid': '12237786', 'emid': '35148801'}
3                     {'trialid': '02360007'}
Name: EN, dtype: object
 

Ответ №3:

Вы можете использовать str.extract :

 df['EN'].str.extract('PubMed Identifier  (?P<pmid>d )|NCT(?P<trialid>d )|Embase  (?P<euid>[^ ] )')
 

выход:

        pmid   trialid euid
0  27955689       NaN  NaN
1   8010359       NaN  NaN
2  12237786       NaN  NaN
3       NaN  02360007  NaN
 

Чтобы иметь как дикт, добавьте .T.to_dict() :

 df['EN'].str.extract('(?=PubMed Identifiers (?P<pmid>[^ ] d ))?|(?=Embases (?P<euid>d ))?').T.to_dict()
 

выход:

 {0: {'pmid': '27955689', 'euid': nan},
 1: {'pmid': '8010359', 'euid': nan},
 2: {'pmid': '12237786', 'euid': nan},
 3: {'pmid': 'NCT02360007', 'euid': nan}}
 

Комментарии:

1. Это близко, но не совсем там wrt для вывода, я должен перейти к просмотру выражений reg и использовать .extract() метод. Это выглядит очень полезным, спасибо.