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
?
假设所考虑的列由 表示s
,我们可以:
在分隔符上拆分"."
以expand=True
生成扩展的DF
.
fnc
:检查分组框架的所有元素是否仅包含,然后用通过列表理解建立的None
虚拟条目替换它们。稍后在过滤列表上调用系列构造函数。随后使用 删除此处存在的任何内容。""
None
dropna
执行groupby
wrt 0和1列名称并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)