我刚接触大熊猫,最近遇到了一个问题。我有一个需要处理的Pandas DataFrame。我需要提取满足特定条件的DataFrame部分。但是,我希望这些部分是连贯的块,而不是一个大集合。
示例: 考虑以下熊猫DataFrame
col1 col2
0 3 11
1 7 15
2 9 1
3 11 2
4 13 2
5 16 16
6 19 17
7 23 13
8 27 4
9 32 3
我想提取col2
> = 10的子帧,结果可能是(在这种情况下)形式的DataFrame列表:
col1 col2
0 3 11
1 7 15
col1 col2
5 16 16
6 19 17
7 23 13
最终,我需要对结果部分中col1
中的值进行进一步分析。但是,每个块的开始和结束对我来说都很重要,所以我认为仅使用pandas.DataFrame.loc
创建一个子集对我来说是行不通的。
我尝试过的事情:
现在,我有一种解决方法,可以使用pandas.DataFrame.loc
获取子集,然后通过迭代子集并检查索引中是否存在跳跃来提取每个相干块的开始索引和结束索引。但是,这感觉很笨拙,而且我觉得这里缺少基本的pandas函数,这会使我的代码更高效,更干净。
这是代表我当前解决方法的代码,适用于以上示例
# here the blocks will be collected for further computations
blocks = []
# get all the items where col2 >10 using 'loc[]'
subset = df.loc[df['col2']>10]
block_start = 0
block_end = None
#loop through all items in subset
for i in range(1, len(subset)):
# if the difference between the current index and the last is greater than 1 ...
if subset.index[i]-subset.index[i-1] > 1:
# ... this is the current blocks end
next_block_start = i
# extract the according block and add it to the list of all blocks
block = subset[block_start:next_block_start]
blocks.append(block)
#the next_block_start index is now the new block's starting index
block_start = next_block_start
#close and add last block
blocks.append(subset[block_start:])
编辑:我以前是错误地指“ pandas.DataFrame.where”而不是“ pandas.DataFrame.loc”。我对最近的研究似乎有些困惑。
答案 0 :(得分:1)
您可以将问题分成几部分。首先,您检查条件:
df['mask'] = (df['col2']>10)
我们使用它来查看新子集的起始位置:
df['new'] = df['mask'].gt(df['mask'].shift(fill_value=False))
现在您可以将这些信息组合成一个组号。如果cumsum
不是我们感兴趣的组,则将生成一个步进函数,我们将其设置为零(通过mask
列)。
df['grp'] = (df.new + 0).cumsum() * df['mask']
编辑
您不必在df
中进行组计算:
s = (df['col2']>10)
s = (s.gt(s.shift(fill_value=False)) + 0).cumsum() * s
之后,您可以将其拆分为dict
个单独的DataFrames
grp = {}
for i in np.unique(s)[1:]:
grp[i] = df.loc[s == i, ['col1', 'col2']]