Как эффективно отфильтровать информационный фрейм панд и вернуть серию панд? - PullRequest
0 голосов
/ 24 сентября 2018

Вопрос кажется простым и спорным на грани глупости.Но, учитывая мой сценарий, мне кажется, что мне нужно было бы сделать именно это, чтобы эффективно провести несколько расчетов по нескольким фреймам данных.

Сценарий:

I 'у нас есть набор фреймов данных pandas, где имена столбцов состоят из части имени и части времени, такой как 'AA_2018' и 'BB_2017'.И я делаю вычисления для разных столбцов из разных фреймов данных, поэтому мне придется отфильтровать временной интервал.Как mcve , давайте просто скажем, что я хотел бы вычесть столбец, содержащий 'AA', из столбца, содержащего 'BB', и игнорировать все остальные столбцы в этом кадре данных:

import pandas as pd
import numpy as np

dates = pd.date_range('20180101',periods=3)
df = pd.DataFrame(np.random.randn(3,3),index=dates,columns=['AA_2018', 'AB_2018', 'BB_2017'])

enter image description here

Если я знал точное имя столбцов, это легко сделать с помощью:

diff_series = df['AA_2018'] - df['BB_2017']

Это вернетсерия панд, так как я использую одиночные скобки [] в отличие от рамки данных. Если бы я использовал двойные скобки [[]].

Моя задача:

diff_series имеет тип pandas.core.series.Series.Но поскольку у меня есть некоторая фильтрация, я использую df.filter(), который возвращает кадр данных с одним столбцом, а не ряд:

# in:
colAA = df.filter(like = 'AA')

# out:
# AA_2018
# 2018-01-01  0.801295
# 2018-01-02  0.860808
# 2018-01-03 -0.728886

# in:
# type(colAA)

# out:
# pandas.core.frame.DataFrame

Snce colAA isтипа pandas.core.frame.DataFrame, следующий фрейм данных также возвращает:

# in:
colAA = df.filter(like = 'AA')
colBB = df.filter(like = 'BB')
df_filtered = colBB - colAA

# out:
            AA_2018  BB_2017
2018-01-01      NaN      NaN
2018-01-02      NaN      NaN
2018-01-03      NaN      NaN    

И это не то, что мне нужно.Это:

# in: 
diff_series = df['AA_2018'] - df['BB_2017']

# out:
2018-01-01    0.828895
2018-01-02   -1.153436
2018-01-03   -1.159985

Почему я непреклонен в этом?

Поскольку я хотел бы получить фрейм данных, используя .to_frame() суказанное имя, основанное на фильтрах, которые я использовал.

Мой предположительно неэффективный подход заключается в следующем:

# in:

colAA_values = [item for sublist in colAA.values for item in sublist]
# (because colAA.values returns a list of lists)

colBB_values = [item for sublist in colBB.values for item in sublist]

serAA = pd.Series(colAA_values, colAA.index)
serBB = pd.Series(colBB_values, colBB.index)

df_diff = (serBB - serAA).to_frame(name = 'someFilter')

# out:

              someFilter
2018-01-01   -0.828895
2018-01-02    1.153436
2018-01-03    1.159985

Что я пробовал / ЧтоЯ надеялся на работу:

# in:
(df.filter(like = 'BB') - df.filter(like = 'AA')).to_frame(name = 'somefilter')

# out:
# AttributeError: 'DataFrame' object has no attribute 'to_frame'

# (Of course because df.filter() returns a one-column dataframe)

Я также надеялся, что можно установить df.filter() для возврата серии панд, но нет.

Я думаю, я мог бы спроситьвместо этого следующие вопросы: How to convert pandas dataframe column to a pandas series? Но, похоже, у него нет и эффективного встроенного oneliner.Большинство результатов поиска обрабатывают наоборот.Я довольно долго возился с потенциальными обходными путями, и очевидное решение может быть прямо за углом, но я надеюсь, что у некоторых из вас есть предложение, как это сделать эффективно.

Все элементы кода для простого копирования и вставки:

import pandas as pd
import numpy as np

dates = pd.date_range('20180101',periods=3)
df = pd.DataFrame(np.random.randn(3,3),index=dates,columns=['AA_2018', 'AB_2018', 'BB_2017'])

#diff_series = df[['AA_2018']] - df[['BB_2017']]
#type(diff_series)

colAA = df.filter(like = 'AA')
colBB = df.filter(like = 'BB')
df_filtered = colBB - colAA

#type(df_filtered)
#type(colAA)
#colAA.values

#colAA.values returns a list of lists that has to be flattened for use in pd.Series
colAA_values = [item for sublist in colAA.values for item in sublist]
colBB_values = [item for sublist in colBB.values for item in sublist]

serAA = pd.Series(colAA_values, colAA.index)
serBB = pd.Series(colBB_values, colBB.index)

df_diff = (serBB - serAA).to_frame(name = 'someFilter')

# Attempts:
# (df.filter(like = 'BB') - df.filter(like = 'AA')).to_frame(name = 'somefilter')

1 Ответ

0 голосов
/ 24 сентября 2018

Вам нужно вместо to_frame - DataFrame.squeeze - преобразовать один столбец DataFrame в Series:

colAA = df.filter(like = 'AA')
colBB = df.filter(like = 'BB')
df_filtered = colBB.squeeze() - colAA.squeeze()
print (df_filtered)
2018-01-01   -0.479247
2018-01-02   -3.801711
2018-01-03    1.567574
Freq: D, dtype: float64
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...