pandas groupby操作缺少数据

epi*_*nio 5 python dataframe pandas

在pandas数据框中,我有一个如下所示的列:

0         M
1         E
2         L
3       M.1
4       M.2
5       M.3
6       E.1
7       E.2
8       E.3
9       E.4
10      L.1
11      L.2
12    M.1.a
13    M.1.b
14    M.1.c
15    M.2.a
16    M.3.a
17    E.1.a
18    E.1.b
19    E.1.c
20    E.2.a
21    E.3.a
22    E.3.b
23    E.4.a
Run Code Online (Sandbox Code Playgroud)

我需要将第一个元素所在的值E, M, or L分组,然后,对于每个组,我需要创建一个子组,其中索引1, 2, or 3将包含每个元素的记录lowercase letter(a,b,c,...)潜在的解决方案应该适用于任意数量的级别连接元素(在这种情况下,级别数为3(例如:A.1.a))

0    1    2
E    1    a
          b
          c
     2    a
     3    a
          b
     4    a
L    1
     2
M    1    a
          b
          c
     2    a
     3    a
Run Code Online (Sandbox Code Playgroud)

我尝试过:

df.groupby([0,1,2]).count()
Run Code Online (Sandbox Code Playgroud)

但结果是缺少L级别,因为它在最后一个子级别没有记录

解决方法是添加一个虚拟变量,然后将其删除...如:

df[2][(df[0]=='L') & (df[2].isnull()) & (df[1].notnull())]='x'
df = df.replace(np.nan,' ', regex=True)
df.sort_values(0, ascending=False, inplace=True)
newdf = df.groupby([0,1,2]).count()
Run Code Online (Sandbox Code Playgroud)

这使:

0    1    2
E    1    a
          b
          c
     2    a
     3    a
          b
     4    a
L    1    x
     2    x
M    1    a
          b
          c
     2    a
     3    a
Run Code Online (Sandbox Code Playgroud)

然后我在代码中稍后处理该dummy条目x...

怎么能避免这种使用方式groupby

Nic*_*eli 1

假设所考虑的列由 表示s,我们可以:

  1. 在分隔符上拆分"."expand=True生成扩展的DF.

  2. fnc:检查分组框架的所有元素是否仅包含,然后用通过列表理解建立的None虚拟条目替换它们。稍后在过滤列表上调用系列构造函数。随后使用 删除此处存在的任何内容。""Nonedropna

  3. 执行groupbywrt 01列名称并fnc应用于2


split_str = s.str.split(".", expand=True)
fnc = lambda g: pd.Series(["" if all(x is None for x in g) else x for x in g]).dropna()
split_str.groupby([0, 1])[2].apply(fnc)
Run Code Online (Sandbox Code Playgroud)

产生:

0  1   
E  1  1    a
      2    b
      3    c
   2  1    a
   3  1    a
      2    b
   4  1    a
L  1  0    
   2  0    
M  1  1    a
      2    b
      3    c
   2  1    a
   3  1    a
Name: 2, dtype: object
Run Code Online (Sandbox Code Playgroud)

要获得展平的DF,请将索引重置为与之前用于分组的级别相同DF

split_str.groupby([0, 1])[2].apply(fnc).reset_index(level=[0, 1]).reset_index(drop=True)
Run Code Online (Sandbox Code Playgroud)

产生:

    0  1  2
0   E  1  a
1   E  1  b
2   E  1  c
3   E  2  a
4   E  3  a
5   E  3  b
6   E  4  a
7   L  1   
8   L  2   
9   M  1  a
10  M  1  b
11  M  1  c
12  M  2  a
13  M  3  a
Run Code Online (Sandbox Code Playgroud)