Изменение формы фрейма данных путем свертывания и создания новых столбцов с помощью Python

#python #reshape

#python #изменение формы

Вопрос:

У меня есть фрейм данных, который выглядит следующим образом:

 data = {'case_id': ['aaa', 'aaa', 'bbb', 'ccc', 'bbb', 'ccc'],
'file_name': ['512.mirnas', '512.isoforms', '360.isoforms', '478.mirnas', '360.mirnas', '478.isoforms']
}

df = pd.DataFrame(data, columns=['case_id', 'file_name'])
 
   case_id     file_name
0     aaa    512.mirnas
1     aaa  512.isoforms
2     bbb  360.isoforms
3     ccc    478.mirnas
4     bbb    360.mirnas
5     ccc  478.isoforms
 

Для каждого уникального «case_id» есть два «file_names», одна mirnas и одна изоформа. Я хочу свернуть «case_id» и создать новые столбцы для имени файла mirnas и изоформ. Я пытаюсь добиться этого:

   case_id file_name_mirnas file_name_isoforms
0     aaa       512.mirnas       512.isoforms
1     bbb       360.mirnas       360.isoforms
2     ccc       478.mirnas       478.isoforms
 

Я совсем новичок в Python, и мне трудно это сделать. Я попробовал в df.pivot, но это не сработало. Я получил следующую ошибку:
ValueError: Index contains duplicate entries, cannot reshape

Я подумал, может быть, я мог бы создать два новых пустых столбца «file_name_mirnas» и «file_name_isoforms», а затем использовать groupby для заполнения этих столбцов. Но я не очень уверен, как это сделать.

Может кто-нибудь, пожалуйста, помочь?

Ответ №1:

Вы можете сделать это, разделив их на разные фреймы данных, а затем объединив их вместе:

Я также заметил, что некоторые значения называются «mirna» вместо «mirnas». Я изменил это для своего ответа.

 import pandas as pd
data = {'case_id': ['aaa', 'aaa', 'bbb', 'ccc', 'bbb', 'ccc'],
'file_name': ['512.mirnas', '512.isoforms', '360.isoforms', '478.mirnas', '360.mirnas', '478.isoforms']
}

df = pd.DataFrame(data, columns=['case_id', 'file_name'])

df_mirnas = df[df["file_name"].str.endswith("mirnas")]  # Grabs all that end with mirnas
df_mirnas.rename(columns={"file_name": "file_name_mirnas"}, inplace=True)  # Rename for join
df_iso = df[df["file_name"].str.endswith("isoforms")]  # Grabs all that ends with isoforms
df_iso.rename(columns={"file_name": "file_name_isoforms"}, inplace=True)  # rename for join

df_new = df_mirnas.join(df_iso.set_index("case_id"), on="case_id") # Joins them on case_id
df_new
 
 >> 
case_id file_name_mirnas    file_name_isoforms
0   aaa 512.mirnas  512.isoforms
3   ccc 478.mirnas  478.isoforms
4   bbb 360.mirnas  360.isoforms
 

PS, я думаю, что groupby очень неинтуитивен в использовании, поэтому не расстраивайтесь из-за того, что вы не всегда его используете (даже если он, вероятно, более эффективен, как здесь)

Ответ №2:

Если вы не знаете запросы в pandas, вы можете сделать это таким образом. 1- разделите строки 2- выберите два имени файлов для каждого случая 3- создание нового фрейма данных

 
from numpy.lib.arraysetops import unique
import pandas as pd

data = {'case_id': ['aaa', 'aaa', 'bbb', 'ccc', 'bbb', 'ccc'],
        'file_name': ['512.mirnas', '512.isoforms', '360.isoforms', '478.mirnas', '360.mirnas', '478.isoforms']
        }

df = pd.DataFrame(data, columns=['case_id', 'file_name'])

print(df)

unique_caseid = sorted(set(df.loc[:, 'case_id']))
mirnas = []
isoforms = []
for id in unique_caseid:
    # first file name
    temp_index = list(df.loc[:, 'case_id']).index(id)
    file_name = df.loc[temp_index, 'file_name']
    if 'mirnas' in file_name:
        mirnas.append(file_name)
    else:
        isoforms.append(file_name)
    # 2nd file name
    ntemp_index = list(df.loc[:, 'case_id'])[temp_index 1:].index(id)
    temp_index  = ntemp_index 1
    file_name = df.loc[temp_index, 'file_name']
    if 'mirnas' in file_name:
        mirnas.append(file_name)
    else:
        isoforms.append(file_name)

data = {}
data['case_id'] = unique_caseid
data['file_name_mirnas'] = mirnas
data['file_name_iosforms'] = isoforms

newdf = pd.DataFrame(
    data, columns=['case_id', 'file_name_mirnas', 'file_name_iosforms'])
print(newdf)


 

Ответ №3:

Вы можете создать временный столбец для хранения mirnas , а isoforms затем использовать функцию pivot для изменения формы ваших данных, прежде чем окончательно свернуть столбцы с пониманием списка:

 df = (df.assign(temp=df.file_name.str.split(".").str[-1])
        .pivot("case_id", "temp")
       )

# flatten columns
df.columns = ["_".join(entry) for entry in df]

df.reset_index()

   case_id  file_name_isoforms  file_name_mirnas
0   aaa     512.isoforms        512.mirnas
1   bbb     360.isoforms        360.mirnas
2   ccc     478.isoforms        478.mirnas