簡體   English   中英

熊貓-計算多個條件

[英]Pandas - count if multiple conditions

在python中有一個數據框:

CASE    TYPE
1          A
1          A
1          A
2          A
2          B
3          B
3          B
3          B

我如何創建一個結果數據框,將產生所有案例,如果案例僅分配了“ A”,則為“ A”,如果僅分配“ B”則為“ B”,如果案例同時為A和B,則為“ MIXED” ?

結果將是:

Case     Type
1        A
2        MIXED
3        B

這是一個選項,我們首先按CASE組收集TYPE作為列表,然后檢查唯一TYPE的length ,如果它大於1 ,則返回MIXED否則返回TYPE本身:

import pandas as pd
import numpy as np
groups = df.groupby('CASE').agg(lambda g: [g.TYPE.unique()]).
            apply(lambda row: np.where(len(row.TYPE) > 1, 'MIXED', row.TYPE[0]), axis = 1)
groups

# CASE
# 1           A
# 2       MIXED
# 3           B
# dtype: object
df['NTYPES'] = df.groupby('CASE').transform(lambda x: x.nunique())
df.loc[df.NTYPES > 1, 'TYPE'] = 'MIXED'
df.groupby('TYPE', as_index=False).first().drop('NTYPES', 1)

    TYPE  CASE
0      A     1
1      B     3
2  MIXED     2

這有點丑陋,但不是那么慢的解決方案:

In [154]: df
Out[154]:
    CASE TYPE
0      1    A
1      1    A
2      1    A
3      2    A
4      2    B
5      3    B
6      3    B
7      3    B
8      4    C
9      4    C
10     4    B

In [155]: %paste
(df.groupby('CASE')['TYPE']
   .apply(lambda x: x.head(1) if x.nunique() == 1 else pd.Series(['MIX']))
   .reset_index()
   .drop('level_1', 1)
)
## -- End pasted text --
Out[155]:
   CASE TYPE
0     1    A
1     2  MIX
2     3    B
3     4  MIX

時間:針對80萬行DF:

In [191]: df = pd.concat([df] * 10**5, ignore_index=True)

In [192]: df.shape
Out[192]: (800000, 3)

In [193]: %timeit Psidom(df)
1 loop, best of 3: 235 ms per loop

In [194]: %timeit capitalistpug(df)
1 loop, best of 3: 419 ms per loop

In [195]: %timeit Alberto_Garcia_Raboso(df)
10 loops, best of 3: 112 ms per loop

In [196]: %timeit MaxU(df)
10 loops, best of 3: 80.4 ms per loop

這是一個(經過過度設計的)解決方案,可以避免在組和DataFrame.apply循環(這些過程很慢,因此,如果您的數據集足夠大,避免它們可能變得很重要)。

import pandas as pd
df = pd.DataFrame({'CASE': [1]*3 + [2]*2 + [3]*3,
                   'TYPE': ['A']*4 + ['B']*4})

我們按CASE分組並計算TYPE的相對頻率為AB

grouped = df.groupby('CASE')
vc = (grouped['TYPE'].value_counts(normalize=True)
                     .unstack(level=0)
                     .fillna(0))

這是vc樣子

CASE   1    2    3
TYPE
A      1.0  0.5  0.0
B      0.0  0.5  0.0

請注意,所有信息都包含在第一行中。 pd.cut將所述行切成垃圾箱可得到所需結果:

tolerance = 1e-10
bins = [-tolerance, tolerance, 1-tolerance, 1+tolerance]
types = pd.cut(vc.loc['A'], bins=bins, labels=['B', 'MIXED', 'A'])

我們得到:

CASE
1        A
2    MIXED
3        B
Name: A, dtype: category
Categories (3, object): [B < MIXED < A]

為了更好地衡量,我們可以重命名types系列:

types.name = 'TYPE'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM