根据值(重复)提取pandas数据帧的子集?

时间:2016-07-26 10:54:10

标签: pandas indexing dataframe duplicates subset

假设我有以下数据框:

elements =  [1,1,1,1,1,2,3,4,5]
df = pd.DataFrame({'elements': elements})
df.set_index(['elements'])
print df
   elements
0      1
1      1
2      1
3      1
4      1
5      2
6      3

我有一个列表[1, 1, 2, 3],我想要一个包含这4个元素的数据帧的子集,例如:

   elements
0      1
1      1   
5      2
6      3

我已经能够通过构建一个计算数组中项目出现次数的dict并通过附加初始数据的子部分来构建新的数据帧来处理它。

您是否了解一些数据框方法以帮助我找到更优雅的解决方案?

在@jezrael评论之后:我必须补充一点,我需要跟踪初始索引(以df为单位)。

我们可以看到df(第一个数据帧)作为资源的存储库,我需要跟踪哪些行/索引归属:

用例是:在df中的元素中给我两个1,一个2和一个3.我会坚持我的行0和1为1,第4行为2,第5行为3。 / p>

2 个答案:

答案 0 :(得分:2)

当且仅当您的Serieslist已排序(否则,请参阅下文),您可以执行以下操作:

L = [1, 1, 2, 3]
df[df.elements.apply(lambda x: x == L.pop(0) if x in L else False)]
       elements
0         1
1         1
5         2
6         3

list.pop(i)返回并删除list处索引i处的值。由于elementsL都已排序,因此弹出子集列表i==0的第一个元素(L)将始终出现在{{{ 1}}。

因此,在elements的{​​{1}}的每次迭代中,lambda将成为:

elements

正如您所看到的,您的列表最后是空的,所以如果它出现问题,您可以事先复制它。或者,您实际上在刚刚创建的新数据框中拥有该信息!

如果未对L进行排序,请创建一个排序副本,在该副本上应用与上面相同的lambda函数,但它的输出将用作原始数据帧的索引(使用值为True的索引) ):

| element |       L      |   Output  |
|=========|==============|===========|
|    1    | [1, 1, 2, 3] |    True   |
|    1    |    [1, 2, 3] |    True   |
|    1    |       [2, 3] |   False   |
|    1    |       [2, 3] |   False   |
|    1    |       [2, 3] |   False   |
|    2    |       [2, 3] |    True   |
|    3    |          [3] |    True   |
|    4    |           [] |   False   | 
|    5    |           [] |   False   | 

HTH

答案 1 :(得分:0)

merge的新列可以通过GroupBy.cumcount提取{/ 3>}来提取。

L = [1,1,2,3]
df1 = pd.DataFrame({'elements':L})

df['g'] = df.groupby('elements')['elements'].cumcount()
df1['g'] = df1.groupby('elements')['elements'].cumcount()

print (df)
   elements  g
0         1  0
1         1  1
2         1  2
3         1  3
4         1  4
5         2  0
6         3  0
7         4  0
8         5  0

print (df1)
   elements  g
0         1  0
1         1  1
2         2  0
3         3  0
print (pd.merge(df,df1, on=['elements', 'g']))
   elements  g
0         1  0
1         1  1
2         2  0
3         3  0

print (pd.merge(df.reset_index(),df1, on=['elements', 'g'])
                  .drop('g', axis=1)
                  .set_index('index')
                  .rename_axis(None))
   elements
0         1
1         1
5         2
6         3