我想将列添加到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'
值均为eqaul为5.在这两种情况下,计数应从5开始
答案 0 :(得分:3)
尝试:
df['z'] = df.y + df.groupby('y').apply(lambda df: pd.Series(range(len(df)))).values
答案 1 :(得分:1)
虽然不是熊猫相关的答案,但是为了摆脱嵌套列表并将其弄平,你可以使用一个简单的列表理解来解决你当前拥有的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()
In [5]: import itertools
In [6]: z
Out[6]: [[1, 2], [5], [10, 11, 12]]
In [7]: merged = list(itertools.chain(*z))
In [8]: merged
Out[8]: [1, 2, 5, 10, 11, 12]
答案 2 :(得分: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)