python-标记系列中的第二组项目

时间:2018-07-26 23:06:28

标签: python list pandas dataframe

我有一个dataframe列,其中包含.csv中的数字列表。这些数字的范围是1-1400,可以重复也可以不重复,并且NaN值几乎可以随机出现在任何地方。

两个例子是

a=[1,4,NaN,5,6,7,...1398,1400,1,2,3,NaN,8,9,...,1398,NaN]

b=[1,NaN,2,3,4,NaN,7,10,...,1398,1399,1400]

我想创建另一个列,该列找到第一个1-1400,并在相同的索引中记录一个“ 1”,如果第二个1-1400存在,则在新索引中将其标记为“ 2”列

我可以想到一些使用临时占位符和其他检查方式的回旋方式,但是我想知道是否可以使用1-3班轮进行此操作

Edit1:我希望只返回一列

a1=[1,1,NaN,1,1,1,...1,1,2,2,2,NaN,2,2,...,2,NaN]

b1=[1,NaN,1,1,1,NaN,1,1,...,1,1,1]

2 个答案:

答案 0 :(得分:2)

您可以使用groupby()cumcount()对每一列中的数字进行计数:

# create new columns for counting
df['a1'] = np.nan
df['b1'] = np.nan

# take groupby for each value in column `a` and `b` and count each value
df.a1 = df.groupby('a').cumcount() + 1
df.b1 = df.groupby('b').cumcount() + 1

# set np.nan as it is
df.loc[df.a.isnull(), 'a1'] = np.nan
df.loc[df.b.isnull(), 'b1'] = np.nan

编辑(收到“不起作用”的评论后):

df['a2'] = df.ffill().a.diff()
df['a1'] = df.loc[df.a2 < 0].groupby('a').cumcount() + 1
df['a1'] = df['a1'].bfill().shift(-1)
df.loc[df.a1.isnull(), 'a1'] = df.a1.max() + 1
df.drop('a2', axis=1, inplace=True)
df.loc[df.a.isnull(), 'a1'] = np.nan

答案 1 :(得分:0)

您可以使用diff来检查以下两个值之间的差是否为负,表示新范围的开始。让我们创建一个数据框:

import pandas as pd
import numpy as np
# to create a dataframe with two columns my range go up to 12 but 1400 is the same
df = pd.DataFrame({'a':[1,4,np.nan,5,10,12,2,3,4,np.nan,8,12],'b':range(1,13)})
df.loc[[4,8],'b'] = np.nan

因为您有'NaN',所以您需要使用ffill来用先前的值填充NaN,并且想要与{{1 }}大于或等于0(我知道它听起来小于0,但此处不完全正确,因为它错过了数据帧的第一行)。例如,对于“ a”列

~

您将获得两行,其中“新”范围开始。要使用此属性创建“ a1”,您可以执行以下操作:

diff

最后,对于几列,您可以执行以下操作:

print (df.loc[~(df.a.ffill().diff()>=0),'a'])
0    1.0
6    2.0
Name: a, dtype: float64

根据我的输入,您将得到:

# put 1 in the rows with a new range start
df.loc[~(df.a.ffill().diff()>=0),'a1'] = 1
# create a mask to select notnull row in a:
mask_a = df.a.notnull()
# use cumsum and ffill on column a1 with the mask_a
df.loc[mask_a,'a1'] = df.loc[mask_a,'a1'].cumsum().ffill()

编辑:您甚至可以为每一列在一行中完成,结果相同:

list_col = ['a','b']
for col in list_col:
    df.loc[~(df[col].ffill().diff()>=0),col+'1'] = 1
    mask = df[col].notnull()
    df.loc[mask,col+'1'] = df.loc[mask,col+'1'].cumsum().ffill()