python-3.x 增加排数,直到我们在Pandas身上达到某种条件

ddrv8njm  于 2022-12-24  发布在  Python
关注(0)|答案(4)|浏览(98)

我有一个数据框

df = pd.DataFrame([["X","day_2"],["Y","day_4"],["Z","day_3"]],columns=["id","day"])
id  day
X   day_2
Y   day_4
Z   day_3

我想增加每个id的行数,直到从day列中提到的下一天开始到达day_5。例如,对于X id day_2,从day_3到day_5有3行,对于Y id,从day_3到day_5只有1行,对于Z,从day_4到day_5有2行,因为day_3在day列中。

    • 预期产出:**

一个二个一个一个
怎么做呢?

64jmpszr

64jmpszr1#

n = 5
out = (df.set_index('id')['day']
       .apply(lambda x: [f'day_{i+1}' for i in range(int(x.split('_')[1]), n)])
       .explode().reset_index())

第一个月

id  day
0   X   day_3
1   X   day_4
2   X   day_5
3   Y   day_5
4   Z   day_4
5   Z   day_5

你可以改变n

dxpyg8gm

dxpyg8gm2#

您可以extract位数,计算缺失值的数量以达到5,repeat行数,并以groupby.cumcount递增值:

s = df['day'].str.extract(r'_(\d+)', expand=False).astype(int)

out = (df
   .assign(n=s)
   .loc[df.index.repeat(s.rsub(5))]
   .assign(day=lambda d: 'day_' + d.pop('n')
                                   .add(d.groupby('id').cumcount().add(1))
                                   .astype(str))
 )
  • 注意:如果需要干净的索引,请添加reset_index(drop=True)。*

输出:

id    day
0  X  day_3
0  X  day_4
0  X  day_5
1  Y  day_5
2  Z  day_4
2  Z  day_5

如果还想包括初始行,请使用变量。注意:

s = df['day'].str.extract(r'_(\d+)', expand=False).astype(int)

out = (df
   .assign(n=s)
   .loc[df.index.repeat(s.rsub(5).add(1))]
   .assign(day=lambda d: 'day_' + d.pop('n')
                                   .add(d.groupby('id').cumcount())
                                   .astype(str))
 )

输出:

id    day
0  X  day_2
0  X  day_3
0  X  day_4
0  X  day_5
1  Y  day_4
1  Y  day_5
2  Z  day_3
2  Z  day_4
2  Z  day_5
kfgdxczn

kfgdxczn3#

直接的方法是

  • 获取每行所需的天数
  • 然后从全天系列中分割出许多天作为列表
  • 分解以将结果展开到行
N = 5

days_needed = df.day.str.split("_").str[-1].astype(int).rsub(N)
days_all    = pd.Series(range(N)).add(1).astype(str).radd("day_")

(df.assign(day=days_needed.apply(lambda n: days_all.iloc[-n:].tolist()))
   .explode("day", ignore_index=True))

得到

id    day
0  X  day_3
1  X  day_4
2  X  day_5
3  Y  day_5
4  Z  day_4
5  Z  day_5

中间值为

In [132]: days_all = pd.Series(range(N)).add(1).astype(str).radd("day_")

In [133]: days_all
Out[133]:
0    day_1
1    day_2
2    day_3
3    day_4
4    day_5
dtype: object

In [134]: days_needed = df.day.str.split("_").str[-1].astype(int).rsub(N)

In [135]: days_needed
Out[135]:
0    3
1    1
2    2
Name: day, dtype: int32

In [136]: days_needed.apply(lambda n: days_all.iloc[-n:].tolist())
Out[136]:
0    [day_3, day_4, day_5]
1                  [day_5]
2           [day_4, day_5]
Name: day, dtype: object
hjzp0vay

hjzp0vay4#

这是我的解决方案,定义旧的df

df = pd.DataFrame([["X","day_2"],["Y","day_4"],["Z","day_3"]],columns=["id","day"]
                  )
df = df.set_index('id')

创建一个新的 Dataframe 来添加行,这比在两个 Dataframe 之间插入 Dataframe 要好

new_df = pd.DataFrame(columns=["id","day"])

添加缺失行的方法

def addRows( dayNum, df, _id):
    while dayNum <= 5:
        df.loc[df.shape[0]] = [_id, 'day_'+str(dayNum)]
        dayNum+=1

实际工作。

for i, r in df.iterrows():
    dayNum = int (r['day'].split('_')[-1] )
    if dayNum <= 5:
        addRows(dayNum, new_df, i )
new_df.set_index('id')

相关问题