如何有效地过滤Pandas数据帧并返回Pandas序列?

2024-10-03 06:30:14 发布

您现在位置:Python中文网/ 问答频道 /正文

这个问题似乎很简单,可以说是近乎愚蠢。但考虑到我的场景,我似乎必须这样做,以保持跨多个数据帧的一系列计算的效率。你知道吗

场景:

我有一堆pandas数据帧,其中列名由名称部分和时间部分构成,比如'AA_2018''BB_2017'。我对不同数据帧的不同列进行计算,所以我必须过滤掉时间段。作为一个mcve我们只想说,我想从包含'BB'的列中减去包含'AA'的列,并忽略此数据帧中的所有其他列:

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']

这将返回一个pandas系列,因为我使用单括号[],而不是使用双括号[[]]的datframe。你知道吗

我的挑战:

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 colAApandas.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?但这似乎也没有一个高效的内置单行线。大多数搜索结果的处理方式相反。我已经花了相当长的时间来处理潜在的解决方案,一个显而易见的解决方案可能就在眼前,但我希望你们中的一些人能就如何有效地做到这一点提出建议。你知道吗

所有代码元素易于复制和粘贴:

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')

Tags: toinpandasdfforfilteritemframe
1条回答
网友
1楼 · 发布于 2024-10-03 06:30:14

您需要to_frame-^{}的对立面-将一列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

相关问题 更多 >