在不同级别(不遍历行)创建运行总数列的最随机的方法是什么?
输入:
import pandas as pd
import numpy as np
df = pd.DataFrame()
df['test'] = np.nan,np.nan,'X','X','X','X',np.nan,'X','X','X','X','X','X',np.nan,np.nan,'X','X'
df['desired_output_level_1'] = np.nan,np.nan,'1','1','1','1',np.nan,'2','2','2','2','2','2',np.nan,np.nan,'3','3'
df['desired_output_level_2'] = np.nan,np.nan,'1','2','3','4',np.nan,'1','2','3','4','5','6',np.nan,np.nan,'1','2'
输出:
test desired_output_level_1 desired_output_level_2
0 NaN NaN NaN
1 NaN NaN NaN
2 X 1 1
3 X 1 2
4 X 1 3
5 X 1 4
6 NaN NaN NaN
7 X 2 1
8 X 2 2
9 X 2 3
10 X 2 4
11 X 2 5
12 X 2 6
13 NaN NaN NaN
14 NaN NaN NaN
15 X 3 1
16 X 3 2
test列只能包含X或nan。连续X的个数是随机的。
在'desired_output_level_1'列中,尝试计算X系列的数量。
在'desired_output_level_2'列中,尝试查找每个系列的持续时间。
有人能帮忙吗?提前谢谢。
也许不是最神奇的方法,但似乎能得到你想要的。
三个要点:
- 我们只对非NaN行进行操作,所以让我们创建一个掩码:
mask = df['test'].notna()
- 对于一级计算,当从NaN到非NaN变化时,通过移动一行很容易进行比较:
df.loc[mask, "level_1"] = (df["test"].isna() & df["test"].shift(-1).notna()).cumsum()
- 对于二级计算,这有点棘手。一种方法是为每个
level_1
组运行计算,并执行.transform
以保留索引:
df.loc[mask, "level_2"] = (
df.loc[mask, ["level_1"]]
.assign(level_2=1)
.groupby("level_1")["level_2"]
.transform("cumsum")
)
最后一步(如果需要)是将列转换为strings
:
df['level_1'] = df['level_1'].astype('Int64').astype('str')
df['level_2'] = df['level_2'].astype('Int64').astype('str')