从以下数据框架中,如何在不诉诸复制/粘贴或中间数据结构的情况下获得拥有两只以上宠物的所有者列表?
BEGIN TRANSACTION
UPDATE t SET Coll2 = 3 WHERE Coll1 = 'A'
UPDATE t SET Coll2 = 1 WHERE Coll1 = 'C'
COMMIT
获取符合条件的布尔系列非常简单:
df = pd.DataFrame([['Jack', 'fuzzy',12], ['Jack', 'furry',13], ['Joe', 'scratchy',3], ['Jack', 'chirpy',40], ['Jeff', 'slithery',9], ['Jack', 'swimmy',1], ['Joe', 'feathery',14], ['Joe', 'oinky',11], ['Jack', 'stampy',1]],
columns=['Owner', 'Pet', 'Age'])
print(df)
Owner Pet Age
0 Jack fuzzy 12
1 Jack furry 13
2 Joe scratchy 3
3 Jack chirpy 40
4 Jeff slithery 9
5 Jack swimmy 1
6 Joe feathery 14
7 Joe oinky 11
8 Jack stampy 1
实际上可以通过复制粘贴df.groupby('Owner').count()['Pet']>2
Owner
Jack True
Jeff False
Joe True
Name: Pet, dtype: bool
语句来提取匹配项( Jack 和 Joe ):
groupby
但是如果条件语句很长,这是一种痛苦,因为每次更改都需要重复。到目前为止发现的唯一另一种方法是将系列重新放回数据框并使用df.groupby('Owner').count()['Pet'][df.groupby('Owner').count()['Pet']>2]
Owner
Jack 5
Joe 3
Name: Pet, dtype: int64
,但这种感觉不可能是hackish:
query()
有比这更好的方法吗?
答案 0 :(得分:2)
您可以将.loc
索引器与过滤功能一起使用。
>>> df.groupby('Owner').Pet.count().loc[lambda p: p > 2]
Owner
Jack 5
Joe 3
Name: Pet, dtype: int64
或者,您可以使用compress
方法。
>>> df.groupby('Owner').Pet.count().compress(lambda p: p > 2)
Owner
Jack 5
Joe 3
Name: Pet, dtype: int64
答案 1 :(得分:2)
选项1
使用pd.factorize
和np.bincount
f, u = pd.factorize(df.Owner.values)
b = np.bincount(f)
m = b > 2
u[m]
array(['Jack', 'Joe'], dtype=object)
或制作一系列
pd.Series(b[m], u[m])
Jack 5
Joe 3
dtype: int64
选项2
使用相同的groupby
两次
<强> 2.1 强>
时髦的lambda
(lambda p: p[p > 2])(df.groupby('Owner').Pet.count())
Owner
Jack 5
Joe 3
Name: Pet, dtype: int64
<强> 2.2 强>
pipe
我宁愿使用@Mitch的回答而不是这个。
df.groupby('Owner').Pet.count().pipe(lambda p: p[p > 2])
Owner
Jack 5
Joe 3
Name: Pet, dtype: int64
<强>时序强>
以下代码
# Multiples of minimum runtime: Smaller is better.
#
pir1 pir2 pir3 mch1 mch2
10 1.0 2.984347 2.907198 2.422435 2.736712
30 1.0 3.396997 3.464083 3.023355 3.353150
100 1.0 3.646931 3.053890 2.586377 2.859365
300 1.0 4.541890 4.037132 3.054388 3.323939
1000 1.0 2.529670 2.438109 2.214494 2.415056
3000 1.0 3.212312 3.739621 3.062538 2.969489
10000 1.0 2.923211 2.807983 2.970712 2.637492
30000 1.0 2.790350 2.830328 2.978083 2.719900
def pir1(d, c):
f, u = pd.factorize(d.Owner.values)
b = np.bincount(f)
m = b > c
return pd.Series(b[m], u[m])
pir2 = lambda d, c: (lambda p: p[p > c])(d.groupby('Owner').Pet.count())
pir3 = lambda d, c: d.groupby('Owner').Pet.count().pipe(lambda p: p[p > c])
mch1 = lambda d, c: d.groupby('Owner').Pet.count().loc[lambda p: p > c]
mch2 = lambda d, c: d.groupby('Owner').Pet.count().compress(lambda p: p > c)
res = pd.DataFrame(
index=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
columns='pir1 pir2 pir3 mch1 mch2'.split(),
dtype=float
)
for i in res.index:
d = pd.concat([df] * i, ignore_index=True)
c = 2 * i
for j in res.columns:
stmt = '{}(d, c)'.format(j)
setp = 'from __main__ import d, c, {}'.format(j)
res.at[i, j] = timeit(stmt, setp, number=10)
res.div(res.min(1), 0)
res.plot(loglog=True)