根据另一个系列,新Pandas系列带有旗帜

2024-07-05 11:44:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个与此类似的数据帧:

>>> d = {'ID': ['ID1', 'ID2', 'ID3', 'ID4', 'ID5', 'ID6', 'ID7', 'ID8', 'ID9', 'ID10'], 
         'A': [1, 1, 1, 1, 2, 2, 2, 2, 2, 2], 
         'B': [145,158,240,250,199,204,300,350,467,578]}
>>> df = pd.DataFrame(data=d)

我想创建一个新的系列F,以标记列B的每100个单元(从列B中的第一个值开始计数,而不是从0开始计数)。列B中的数字对于列A中的每个数字都“重新启动”。对于列A中的新数字,它应该启动一个新标志,并将列B中的相应值作为新范围100的第一个数字。澄清一下,这种情况的预期结果是:

>>> outcome = {'ID': ['ID1', 'ID2', 'ID3', 'ID4', 'ID5', 'ID6', 'ID7', 'ID8', 'ID9', 'ID10'], 
           'A': [1, 1, 1, 1, 2, 2, 2, 2, 2, 2], 
           'B': [145,158,240,250,199,204,300,350,467,578],
           'F': ['F1','F1','F1','F2','F3','F4','F4','F5','F6','F7']}
>>> outcome
      A    B    F
ID1   1   145   F1
ID2   1   158   F1
ID3   1   240   F1
ID4   1   250   F2
ID5   2   199   F3
ID6   2   204   F3
ID7   2   300   F4
ID8   2   350   F4
ID9   2   467   F5
ID10  2   578   F6

我希望这一切都有意义,提前谢谢


Tags: id数字f1id3id2f3id1f4
3条回答

这是我提议的(暴力)解决方案:

df = df.reset_index()                # iloc is easier with a clean integer index
B0 = df['B'][0]                      # initialize B

df['F'] = ''                         # create a result column 'F'
df.loc[0,'F'] = 'F1'                 # set the first result
idx = 1                              # initialize your index 
for i in range(1,len(df)):           # iterate over all rows
    if(df['A'][i] == df['A'][i-1]):  # condition 1 : Ai == Ai-1
        if((df['B'][i]-B0)>100):     # condition 2 : Bi - B0 > 100
            idx += 1                 # increment index
            B0 = df.loc[i,'B']       # reset B0
    else:                            # Ai != Ai-1
        idx +=1                      # increment index
        B0 = df.loc[i,'B']           # reset B0

    df.loc[i,'F'] = 'F' + str(idx)   # set output Fi

有兴趣看看是否有人能提供一个更漂亮的解决方案

我想到了一个简短但可读性较差的简化,我将其作为另一个答案发布,让您选择您喜欢的:

df = df.reset_index()                # iloc is easier with a clean integer index
B0 = df['B'][0]                      # initialize B

df['F'] = ''                         # create a result column 'F'
df.loc[0,'F'] = 'F1'                 # set the first result
idx = 1                              # initialize your index 
for i in range(1,len(df)):           # iterate over all rows
    if(df['A'][i] != df['A'][i-1]) |  if((df['B'][i]-B0)>100):     # combining both conditions
        idx += 1                 # increment index
        B0 = df.loc[i,'B']       # reset B0

    df.loc[i,'F'] = 'F' + str(idx)   # set output Fi

你可以做:

import numpy as np

df['d100'] = df.groupby('A')['B'].diff().fillna(0)
df['d100'] = df.groupby('A')['d100'].cumsum() // 100

df['F'] = np.where(df['A'].ne(df['A'].shift()) | df['d100'].ne(df['d100'].shift()), 1, 0).cumsum()
df['F'] = 'F' + df['F'].astype(str)

df.drop('d100', axis=1, inplace=True)

产出:

     ID  A    B   F
0   ID1  1  145  F1
1   ID2  1  158  F1
2   ID3  1  240  F1
3   ID4  1  250  F2
4   ID5  2  199  F3
5   ID6  2  204  F3
6   ID7  2  300  F4
7   ID8  2  350  F4
8   ID9  2  467  F5
9  ID10  2  578  F6

相关问题 更多 >