pandas groupby操作缺少数据

时间:2017-02-13 01:52:33

标签: python pandas dataframe

在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

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

lowercase letter

我尝试过:

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

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

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

df.groupby([0,1,2]).count()

给出:

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

然后我在代码中处理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 条目dummy ...

如何避免这种使用x的方式?

2 个答案:

答案 0 :(得分:1)

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

  1. "."分隔符上与expand=True分开,以生成展开的DF

  2. fnc:检查分组帧的所有元素是否仅由None组成,然后用虚拟条目""替换它们,该条目通过建立列表理解。稍后在筛选列表上调用一系列构造函数。随后使用None删除此处的任何dropna

  3. 执行groupby w.r.t. 0 & 1 列名并将fnc应用于 2

  4. 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)
    

    产生

    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
    

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

    split_str.groupby([0, 1])[2].apply(fnc).reset_index(level=[0, 1]).reset_index(drop=True)
    

    产生

        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
    

答案 1 :(得分:0)

也许你必须找到一种使用正则表达式的方法。

import pandas as pd

df = pd.read_clipboard(header=None).iloc[:, 1]
df2 = df.str.extract(r'([A-Z])\.?([0-9]?)\.?([a-z]?)')
print df2.set_index([0,1])

结果是,

     2
0 1   
M     
E     
L     
M 1   
  2   
  3   
E 1   
  2   
  3   
  4   
L 1   
  2   
M 1  a
  1  b
  1  c
  2  a
  3  a
E 1  a
  1  b
  1  c
  2  a
  3  a
  3  b
  4  a