Python 熊猫基于上一列获取计数

Python 熊猫基于上一列获取计数,python,pandas,Python,Pandas,我想将列添加到一个数据帧中,其中的值是一个递增的值,从另一列的值开始。例如,假设我有以下数据帧 df = pd.DataFrame([['a', 1], ['a', 1], ['b', 5], ['c', 10], ['c', 10], ['c', 10]], columns=['x', 'y']) df x y 0 a 1 1 a 1 2 b 5 3 c 10 4 c 10 5 c 10 是否有一些pandas功能会返回一个系列,

我想将列添加到一个数据帧中,其中的值是一个递增的值,从另一列的值开始。例如,假设我有以下数据帧

df = pd.DataFrame([['a', 1], ['a', 1], ['b', 5], ['c', 10], ['c', 10], ['c', 10]], columns=['x', 'y'])
df

    x   y
0   a   1
1   a   1
2   b   5
3   c   10
4   c   10
5   c   10
是否有一些pandas功能会返回一个系列,每个组的值都在增加?换句话说,
'a'
将以
1
开头,
'b'
5
开头,
'c'
10
开头。输出序列将是
(1,2,5,10,11,12)
,因此可以像这样将其添加到原始数据帧中:

    x   y   z
0   a   1   1
1   a   1   2
2   b   5   5
3   c   10  10
4   c   10  11
5   c   10  12
我尝试了以下方法:

z = []
for start, length in zip(df.y.unique(), df.groupby('x').agg('count')['y']):
    z.append(list(range(start, length + start)))
np.array(z).flatten()
z

[[1, 2], [5], [10, 11, 12]]
这并不能完全满足我的需要,我不知道为什么阵列不能展平,对于一个看似简单的任务来说,它似乎过于复杂

编辑: 该解决方案还应可扩展到更复杂的数据帧,例如:

df = pd.DataFrame([['a', 1], ['b', 5], ['c', 10], ['d', 5]], columns=['x', 'y'])
df = df.append([df]*(50),ignore_index=True)
其中,“x”列中的
'a'
'b'
值等于5。在这两种情况下,计数应从5开始,请尝试:

df['z'] = df.y + df.groupby('y').apply(lambda df: pd.Series(range(len(df)))).values
尝试:


虽然不是一个与熊猫相关的答案,但要摆脱嵌套列表并将其展平,您可以使用一个简单的列表理解来理解您当前拥有的z

>>>z = [[1, 2], [5], [10, 11, 12]]
>>>z_flat = [num for sublist in z for num in sublist])
>>>z_flat
[1, 2, 5, 10, 11, 12]
编辑:当然,为了更快地转换,可以使用itertools.chain()


虽然不是一个与熊猫相关的答案,但要摆脱嵌套列表并将其展平,您可以使用一个简单的列表理解来理解您当前拥有的z

>>>z = [[1, 2], [5], [10, 11, 12]]
>>>z_flat = [num for sublist in z for num in sublist])
>>>z_flat
[1, 2, 5, 10, 11, 12]
编辑:当然,为了更快地转换,可以使用itertools.chain()


与@piRSquared的方法相比,这里有一种更丑陋的方法:

def func(group):
    x = group['y'].head(1).values
    l = []
    for i in range(len(group)):
        l.append(x+i)
    return pd.Series(l, name='z')

x = df.groupby('x').apply(func).reset_index().drop('level_1', axis=1)
x['z'] = x['z'].apply(lambda x: x[0])
pd.concat([df, x['z']], axis=1)

与@piRSquared的方法相比,这里有一种更丑陋的方法:

def func(group):
    x = group['y'].head(1).values
    l = []
    for i in range(len(group)):
        l.append(x+i)
    return pd.Series(l, name='z')

x = df.groupby('x').apply(func).reset_index().drop('level_1', axis=1)
x['z'] = x['z'].apply(lambda x: x[0])
pd.concat([df, x['z']], axis=1)

使用
z.extend(range(start,length+start))
而不是
z.append…
使用
z.extend(range(start,length+start))
而不是
z.append…
这是一个很好的解决方案,但是它不会扩展到更复杂的情况。我更新了问题以澄清我的意思。我问题中的解决方案也没有考虑到这一点,但我一直在考虑如何实现它。根据您的建议,this
df['z']=df.groupby('x')。apply(lambda x:x['y']+range(len(x))。value
似乎完成了我试图完成的任务。这是一个好的解决方案,但它不会扩展到更复杂的情况。我更新了问题以澄清我的意思。我的问题中的解决方案也没有考虑到这一点,但根据您的建议,我一直在思考如何实现它。这个
df['z']=df.groupby('x')。应用(lambda x:x['y']+range(len(x))。值
似乎完成了我试图做的事情。