Pandas: более быстрый способ сложного преобразования столбца с помощью функции поворота - PullRequest
2 голосов
/ 30 мая 2019

Проще говоря, мне нужно преобразовать следующий входной фрейм данных в вывод ниже.

После нескольких часов попыток выяснить, как, комбинируя несколько предыдущих вопросов о стековом потоке, я мог преобразовать фрейм данных, но преобразование большого фрейма данных занимает очень много времени, так как я использую метод pivot и apply.

import numpy as np
import pandas as pd
df = pd.DataFrame({"id":[1,2,3,4,5],
                  "day":pd.Timestamp('20190529'),
                  "subject":"math,english,economics",
                  "score":pd.Categorical(["68,62,49","58,72,87","28,32,46","48,72,66","46,25,93"]),
                  "Department":pd.Categorical(["Economics","Computer Science","Sociology","Business","Math"])})


---Input DataFrame---

    id    day           subject                score       Department
0   1   2019-05-29  math,english,economics    68,62,49    Economics
1   2   2019-05-29  math,economics             58,87       Computer Science
2   3   2019-05-29  philosophy,english,business 28,32,46    Sociology
3   4   2019-05-29  physics,sociology           72,66      Business
4   5   2019-05-29  Math                          93          Math

И вывод похож на тот, что показан ниже

---Output DataFrame---

id  day         Department          Math business economics english math philosophy physics sociology
1   2019-05-29  Economics           NaN NaN 49  62  68  NaN NaN NaN
2   2019-05-29  Computer Science    NaN NaN 87  NaN 58  NaN NaN NaN
3   2019-05-29  Sociology           NaN 46  NaN 32  NaN 28  NaN NaN
4   2019-05-29  Business            NaN NaN NaN NaN NaN NaN 72  66
5   2019-05-29  Math                93  NaN NaN NaN NaN NaN NaN NaN

И мой подход -

  1. Я делю столбцы темы и оценки на ','.
  2. Разнесите список элементов в столбцах темы и оценки, чтобы разделить строку как pandas.Series
  3. Присоединитесь к каждому pandas.Series, чтобы создать новый фрейм данных
  4. Повернуть новый фрейм данных, созданный на шаге 3
  5. Удалите столбец темы и оценки в исходном фрейме данных
  6. Соедините каждый фрейм данных, созданный на шаге 4 и шаге 5

И мой код выглядит следующим образом

df["subject"] = df["subject"].str.split(",")
df["score"] = df["score"].str.split(",")

subject = df.apply(lambda x: pd.Series(x['subject']),axis=1).stack().reset_index(level=1, drop=True)
score = df.apply(lambda x: pd.Series(x['score']),axis=1).stack().reset_index(level=1, drop=True)
subject.name = 'subject'
score.name = 'score'

subject_score = pd.concat([subject, score],join='outer', axis=1)
pdf = df.drop('subject', axis=1).drop("score", axis=1).join(subject_score)

pivot = pdf.pivot(columns="subject",values="score")
concate_table = df.drop("subject",axis = 1).drop("score", axis=1)
output = concate_table.join(pivot)

Я только недавно начал изучать панд, и я уверен, что это не лучший способ перестановки столбцов.

Если бы вы могли дать мне несколько советов, как оптимизировать этот код, я ценю.

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 30 мая 2019

Я бы определил пользовательскую функцию stack_str для распаковки строкового столбца в фрейм данных, используя expand=True и stack и reset_index для серии.

Примените stack_str к 2 столбцам строк, чтобы получить df1 из 2 столбцов.

Затем выполните pivot на df1, чтобы сделать subject значениями как columns и scores как values.Наконец, присоединитесь к df уже отброшенным 2 столбцам, имеющим строки.

def stack_str(x):
        s = x.str.split(',', expand=True).stack().reset_index(level=-1, drop=True)
        return s

df1 = df[['subject', 'score']].apply(stack_list)

Out[984]:
      subject score
0        math    68
0     english    62
0   economics    49
1        math    58
1   economics    87
2  philosophy    28
2     english    32
2    business    46
3     physics    72
3   sociology    66
4        Math    93

df2 = df.drop(['subject', 'score'], axis=1).join(df1.pivot(columns='subject', values='score'))

Out[986]:
   id         day        Department Math business economics english math  \
0   1  2019-05-29         Economics  NaN      NaN        49      62   68
1   2  2019-05-29  Computer_Science  NaN      NaN        87     NaN   58
2   3  2019-05-29         Sociology  NaN       46       NaN      32  NaN
3   4  2019-05-29          Business  NaN      NaN       NaN     NaN  NaN
4   5  2019-05-29              Math   93      NaN       NaN     NaN  NaN

  philosophy physics sociology
0        NaN     NaN       NaN
1        NaN     NaN       NaN
2         28     NaN       NaN
3        NaN      72        66
4        NaN     NaN       NaN
0 голосов
/ 30 мая 2019

Я использую unnesting , затем с pivot и concat back

s=df[['subject','score']]
s=unnesting(s.apply(lambda x :x.str.split(','),1),['subject','score']).pivot(columns='subject',values='score')
df=pd.concat([df,s],axis=1)

def unnesting(df, explode):
    idx = df.index.repeat(df[explode[0]].str.len())
    df1 = pd.concat([
        pd.DataFrame({x: np.concatenate(df[x].values)}) for x in explode], axis=1)
    df1.index = idx

    return df1.join(df.drop(explode, 1), how='left')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...