我有一个pandas数据框如下。
d = {'emp': ['a', 'a', 'a', 'b', 'b', 'b'], 'vendor': ['x', 'x', 'y', 'z', 'z', 'z'], 'date': [1,1,2,3,3,3], 'amount': [4.9, 4.8, 1, 6, 5.6, 5.4]}
df = pd.DataFrame(data=d)
df["rounds"]=np.ceil(df['amount'])
df
amount date emp vendor rounds
0 4.9 1 a x 5.0
1 4.8 1 a x 5.0
2 1.0 2 a y 1.0
3 6.0 3 b z 6.0
4 5.6 3 b z 6.0
5 5.4 3 b z 6.0
我想创建example
列,如果同一emp
在相同的rounds
上花费相同的金额(列vendor
),则该列会有唯一的数字同一天。
员工可能有多个符合此条件的交易,或者他们可能有0个符合此条件的交易
我该怎么办?
example
1
1
2
2
2
如果example
列中的数字相同,则表示属于一个组的所有交易
另一个例子
如果我的数据框如下所示
d = {'emp': ['a', 'a', 'a', 'a', 'b', 'b'], 'vendor': ['x', 'x', 'y', 'y', 'z', 'z'], 'date': [1,1,2,2,3,3], 'amount': [4.9, 4.8, 1, 1, 5.6, 5.4]}
然后列example
应该有值' 1,1,2,2,3,3'
答案 0 :(得分:4)
duplicated
内进行 transform
调用,重复会查找每个群组的供应商有多少重复项目,然后我们只需添加它们,就可以实现您的需求,transform你可以查看链接
df.groupby(['date','emp','rounds']).vendor.transform(lambda x : x.duplicated().sum())
Out[806]:
0 1
1 1
2 0
3 2
4 2
5 2
Name: vendor, dtype: int64
分配后
df['example']=df.groupby(['date','emp','rounds']).vendor.transform(lambda x : x.duplicated().sum())
#yield
df
Out[808]:
amount date emp vendor rounds example
0 4.9 1 a x 5.0 1
1 4.8 1 a x 5.0 1
2 1.0 2 a y 1.0 0
3 6.0 3 b z 6.0 2
4 5.6 3 b z 6.0 2
5 5.4 3 b z 6.0 2
更新:
df['key']=tuple(zip(df.emp,df.vendor,df.date,df.rounds))
df[df.duplicated('key',keep=False)].groupby('key').ngroup()+1
Out[831]:
0 1
1 1
2 2
3 2
4 3
5 3
dtype: int64
答案 1 :(得分:1)
不确定如何在SQL中使用Pandas:
# dp is a list of boolean showing whether the elements have duplicates
# setting keep=False returns all the duplicated elements as True
dp = df.duplicated(['date', 'emp', 'rounds'], keep=False)
# dp.dff().ne() means if the next element is no longer a duplicate
# then it's true, cumsum just increments the id
df['example'] = dp.diff().ne(0).cumsum()
df
amount date emp vendor rounds example
0 4.9 1 a x 5.0 1
1 4.8 1 a x 5.0 1
2 1.0 2 a y 1.0 2
3 6.0 3 b z 6.0 3
4 5.6 3 b z 6.0 3
5 5.4 3 b z 6.0 3
答案 2 :(得分:1)
你可以做到
df["tmp"] = df.duplicated(subset = ["date", "amp", "rounds"])
df2 = df.set_index(["date", "emp"])
df2["example"]= df.groupby(["date", "emp"])["tmp"].sum()
df2 = df2.drop("tmp", 1).reset_index()
date emp amount vendor rounds example
0 1 a 4.9 x 5.0 1.0
1 1 a 4.8 x 5.0 1.0
2 2 a 1.0 y 1.0 0.0
3 3 b 6.0 z 6.0 2.0
4 3 b 5.6 z 6.0 2.0
5 3 b 5.4 z 6.0 2.0
我们从您提供的df
开始。第一行
df["tmp"] = df.duplicated(subset = ["date", "amp", "rounds"])
创建一个临时列,指示行是否重复,即
amount date emp vendor rounds tmp
0 4.9 1 a x 5.0 False
1 4.8 1 a x 5.0 True
2 1.0 2 a y 1.0 False
3 6.0 3 b z 6.0 False
4 5.6 3 b z 6.0 True
5 5.4 3 b z 6.0 True
第二行和第三行
df2 = df.set_index(["date", "emp"])
df2["example"]= df.groupby(["date", "emp"])["tmp"].sum()
只需将date
和emp
组的总和分配到列example
即可。它通过将索引设置为相同来完成此操作。
当两个数据帧具有相同的索引时,即使行数不同,您也可以将一个值分配给另一个:pandas
将推断只要索引相同,值就应该重复。< / p>
最后一栏只删除了tmp
。
答案 3 :(得分:1)
如果您想要一个与根据该分组中的值生成的每个分组相关联的唯一编号,您可以使用散列函数,例如md5
:
from hashlib import md5
cols = ['emp','rounds','vendor','date']
def get_unique_id(x):
if len(x) > 1:
unique_string = ''.join(x.astype(str).values.flatten()).encode('utf8')
unique_hash = str(int(md5(unique_string).hexdigest(), 16))
return unique_hash
# use groupby to get unique groupings, then compute group hash id
grouped = df.groupby(cols).apply(get_unique_id).reset_index()
# merge with original df
df.merge(grouped, how="left", on=cols).rename(columns={0:'example'})
amount date emp vendor rounds example
0 4.9 1 a x 5.0 204218359197769197011002751402112550616
1 4.8 1 a x 5.0 204218359197769197011002751402112550616
2 1.0 2 a y 1.0 None
3 6.0 3 b z 6.0 93359096665893457037712279020314596965
4 5.6 3 b z 6.0 93359096665893457037712279020314596965
5 5.4 3 b z 6.0 93359096665893457037712279020314596965