让我们说我有一个数据框:
function reverse(array,item){
let word = Math.ceil(array.length/2)
array.splice(word,0,item)
return array
}
console.log(reverse([1,2,4,5,6],3))
我想对这些数据进行分组,并比较组df = pd.DataFrame({'a':[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3],
'b':[2016, 2017, 2018, 2019, 2000, 2000, 2000, 2000, 2007, 2008, 2014]})
中少于其他年份的年数。
在第1组中,2016年是第0年,然后2017年是第1年(或落后第1年)。
我尝试做:
a
但这要花很长时间。我想知道是否有更好的方法。我正在处理650万行。
预期输出:
df['c'] = df.groupby('a')['b'].apply(lambda x: [sum(y > x) for y in x]).reset_index(drop=False)
答案 0 :(得分:1)
我会使用rank
,然后再使用sub
1,我认为它非常易读,大约是其他答案的两倍,是原始方法的约3.5倍:
df.groupby(['a'])['b'].rank('min').sub(1)
#0 0.0
#1 1.0
#2 2.0
#3 3.0
#4 0.0
#5 0.0
#6 0.0
#7 0.0
#8 0.0
#9 1.0
#10 2.0
%timeit df.groupby(['a'])['b'].rank('min').sub(1)
#1.58 ms ± 61.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit df.groupby('a')['b'].transform(lambda x: pd.factorize(x)[0])
#3.76 ms ± 330 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit df.groupby('a')['b'].apply(lambda x: [sum(y > x) for y in x]).reset_index(drop=False)
#5.32 ms ± 129 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
答案 1 :(得分:1)
numpy
解决方案
from scipy.stats import rankdata
np.concatenate([rankdata(x,method='min')for x in (np.split(df.b.values,np.flatnonzero(df.a.diff().fillna(0))))])-1
%timeit df.groupby(['a'])['b'].rank('min').sub(1)
1000 loops, best of 3: 845 µs per loop
%timeit df.groupby('a')['b'].transform(lambda x: pd.factorize(x)[0])
100 loops, best of 3: 1.77 ms per loop
%timeit df.groupby('a')['b'].apply(lambda x: [sum(y > x) for y in x]).reset_index(drop=False)
100 loops, best of 3: 2.71 ms per loop
%timeit np.concatenate([rankdata(x,method='min')for x in (np.split(df.b.values,np.flatnonzero(df.a.diff().fillna(0))))])-1
1000 loops, best of 3: 342 µs per loop
答案 2 :(得分:0)
干净高效的解决方案:
import pandas as pd
df = pd.DataFrame({'a':[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3],
'b':[2016, 2017, 2018, 2019, 2000, 2000, 2000, 2000, 2007, 2008, 2014]})
df=df.set_index('a')
df=df.sort_index()
quickmap={}
for index in df.index.unique():
temphash={}
val=0
for i in df.loc[index]['b'].unique():
temphash[i]=val
val+=1
quickmap[index]=temphash
df=df.reset_index()
def toret(row):
key=row['a']
subkey=row['b']
return quickmap[key][subkey]
df['c']=df.apply(toret,axis=1)