有条件地将来自不同数据框的聚合列连接到新的DataFrame中

时间:2015-04-02 23:31:58

标签: python pandas

我有几个具有以下结构的DataFrame:

In [22]: arrays = [np.array(['A1', 'A1', 'A1', 'A1', 'A2', 'A2', 'A2', 'A2']),
   ....:           np.array(['B1', 'B1', 'B2', 'B2', 'B1', 'B1', 'B2', 'B2']),
   ....:           np.array(['C1', 'C2', 'C1', 'C2', 'C1', 'C2', 'C1', 'C2'])]
In [23]: df1 = pd.DataFrame(np.random.randint(10, size=(8, 4)), index=arrays)
In [24]: df1
Out[24]: 
          0  1  2  3
A1 B1 C1  2  7  3  4
      C2  6  2  1  7
   B2 C1  3  3  5  6
      C2  9  6  3  6
A2 B1 C1  7  8  0  6
      C2  6  3  1  6
   B2 C1  9  3  8  2
      C2  7  1  2  8

In [25]: df2 = pd.DataFrame(np.random.randint(10, size=(8, 4)), index=arrays)
In [26]: df2
Out[26]: 
          0  1  2  3
A1 B1 C1  7  2  5  2
      C2  0  2  9  0
   B2 C1  2  2  6  9
      C2  4  6  3  8
A2 B1 C1  7  1  5  1
      C2  6  2  2  6
   B2 C1  5  8  1  6
      C2  7  4  8  0

我想构建以下DataFrame。

max是“0”子阵列中的最大值;

如果第一级索引值在“3”子阵列中包含“1”和第0个元素,则

nth是“2”子阵列中的第0个元素。

             df1       df2
        max  nth  max  nth
A1  B1    6    3    7    5
    B2    9    5    4    6  
A2  B1    7    6    7    1
    B2    9    2    7    6

我尝试df[0].groupby(level=[0, 1]).max()来计算maxdf[2 or 3].groupby(level=[0, 1]).nth(0)来计算nth,但是使用索引值作为选择第2列或第3列的条件而使用连接。

2 个答案:

答案 0 :(得分:1)

这是我的起点(与你的代码相同,不同的随机值):

          0  1  2  3
A1 B1 C1  3  4  1  6
      C2  6  3  4  5
   B2 C1  8  3  5  1
      C2  8  5  1  6
A2 B1 C1  8  7  0  6
      C2  5  1  4  7
   B2 C1  3  1  8  5
      C2  7  1  7  8

df[0] = df.groupby(level=[0,1])[0].transform(max)

          0  1  2  3
A1 B1 C1  6  4  1  6
      C2  6  3  4  5
   B2 C1  8  3  5  1
      C2  8  5  1  6
A2 B1 C1  8  7  0  6
      C2  8  1  4  7
   B2 C1  7  1  8  5
      C2  7  1  7  8

我找不到在第一级直接检查“1”的方法,所以我只是将其转换为带有reset_index的colunn然后在它上面使用字符串方法相当容易。< / p>

df['one'] = df.reset_index().level_0.str.contains('1').values
df['nth'] = np.where( df.one, df[2], df[3] )

          0  1  2  3    one  nth
A1 B1 C1  6  4  1  6   True    1
      C2  6  3  4  5   True    4
   B2 C1  8  3  5  1   True    5
      C2  8  5  1  6   True    1
A2 B1 C1  8  7  0  6  False    6
      C2  8  1  4  7  False    7
   B2 C1  7  1  8  5  False    5
      C2  7  1  7  8  False    8

现在清理一下(其中一些可以提前完成,但我认为更清楚的是等到最后并将它们全部结合起来):

df.iloc[0::2,[0,-1]].reset_index(level=2,drop=True).rename(columns={0:'max'})

       max  nth
A1 B1    6    1
   B2    8    5
A2 B1    8    6
   B2    7    5

我不确定你是否也在询问concat,但这很简单:

pd.concat( [df1,df2], axis=1)

答案 1 :(得分:0)

我设法实现了我想要的解决方案:

In [55]: df = pd.DataFrame()
In [56]: for t, n in [(df1, 'df1'), (df2, 'df2')]:
   ....:     t['nth'] = np.where(t.index.get_level_values(0).to_series().str.contains('1').values, t[2], t[3])
   ....:     df[n, 'max'] = t[0].groupby(level=[0, 1]).max()
   ....:     # reset_index() is required since nth() doesn't reduce number of index levels
   ....:     df[n, 'nth'] = t['nth'].groupby(level=[0, 1]).nth(0).reset_index(level=2, drop=True)
In [57]: df
Out[57]: 
       (df1, max)  (df1, nth)  (df2, max)  (df2, nth)
A1 B1           8           1           7           0
   B2           6           3           9           3
A2 B1           7           2           7           3
   B2           8           2           6           7

In [58]: df.columns = pd.MultiIndex.from_tuples(df.columns)
In [59]: df
Out[59]: 
      df1     df2    
      max nth max nth
A1 B1   8   1   7   0
   B2   6   3   9   3
A2 B1   7   2   7   3
   B2   8   2   6   7