簡體   English   中英

python pandas dataframe:刪除選定的行

[英]python pandas dataframe : removing selected rows

我有一個pandas數據幀,如:

df = pd.read_csv('fruit.csv')

print(df)

   fruitname  quant
0      apple     10
1      apple     11
2      apple     13
3     banana     10
4     banana     20
5     banana     30
6     banana     40
7       pear     10
8       pear    102
9       pear   1033
10      pear   1012
11      pear    101
12      pear    100
13      pear   1044
14    orange     10

我想刪除最后一個條目PER FRUIT,如果該水果有一個奇數(不均勻)條目數(%2 == 1)。 沒有循環數據幀。 所以上面的最終結果是:

- 刪除最后一個蘋果,因為蘋果發生3次 - 去除最后一個梨 - 刪除最后一個(僅)橙色

導致:

   fruitname  quant
0      apple     10
1      apple     11
2     banana     10
3     banana     20
4     banana     30
5     banana     40
6       pear     10
7       pear    102
8       pear   1033
9       pear   1012
10      pear    101
11      pear    100

這可能嗎? 或者我必須循環DF? 我一直在谷歌搜索4天,只是無法弄清楚如何做到這一點。

使用value_counts確定每個水果的項目數,並根據是否存在奇數來構建它們的列表。 我們可以通過使用%模數運算符生成10來實現這一點,使用astype來構建astype以創建一個布爾掩碼。

使用布爾掩碼來掩蓋value_counts的索引。

現在你有一個水果列表,通過過濾df迭代每個水果,並使用iloc[-1].name屬性獲取最后一個索引標簽,並將其附加到列表中。

現在drop這些標簽放在列表中:

In [393]:
fruits = df['fruitname'].value_counts().index[(df['fruitname'].value_counts() % 2).astype(bool)]
idx = []
for fruit in fruits:
    idx.append(df[df['fruitname']==fruit].iloc[-1].name)
df.drop(idx)

Out[393]:
   fruitname  quant
0      apple     10
1      apple     11
3     banana     10
4     banana     20
5     banana     30
6     banana     40
7       pear     10
8       pear    102
9       pear   1033
10      pear   1012
11      pear    101
12      pear    100

突破以上:

In [394]:
df['fruitname'].value_counts()

Out[394]:
pear      7
banana    4
apple     3
orange    1
Name: fruitname, dtype: int64

In [398]:   
df['fruitname'].value_counts() % 2

Out[398]:
pear      1
banana    0
apple     1
orange    1
Name: fruitname, dtype: int64

In [399]:
fruits = df['fruitname'].value_counts().index[(df['fruitname'].value_counts() % 2).astype(bool)]
fruits

Out[399]:
Index(['pear', 'apple', 'orange'], dtype='object')

In [401]:    
for fruit in fruits:
    print(df[df['fruitname']==fruit].iloc[-1].name)

13
2
14

實際上你可以使用last_valid_index而不是iloc[-1].name所以以下方法可行:

fruits = df['fruitname'].value_counts().index[(df['fruitname'].value_counts() % 2).astype(bool)]
idx = []
for fruit in fruits:
    idx.append(df[df['fruitname']==fruit].last_valid_index())
df.drop(idx)

EdChum的另一種方法,它使用groupby

>>> grouped = df.groupby("fruitname")["fruitname"]
>>> lengths = grouped.transform(len)
>>> df.loc[~((lengths % 2 == 1) & (grouped.cumcount() == lengths-1))]
   fruitname  quant
0      apple     10
1      apple     11
3     banana     10
4     banana     20
5     banana     30
6     banana     40
7       pear     10
8       pear    102
9       pear   1033
10      pear   1012
11      pear    101
12      pear    100

這通過使用transform (和cumcount ,其行為類似於一種變換,因為它廣播到原始索引)來為我們提供一個我們可以使用的幀長系列:

>>> lengths
0     3
1     3
2     3
3     4
4     4
5     4
6     4
7     7
8     7
9     7
10    7
11    7
12    7
13    7
14    1
Name: fruitname, dtype: object
>>> grouped.cumcount()
0     0
1     1
2     2
3     0
4     1
5     2
6     3
7     0
8     1
9     2
10    3
11    4
12    5
13    6
14    0
dtype: int64

你可以使用apply函數:

def remove_last_odd_row(fr):
    nrow = fr.shape[0]
    if nrow % 2 > 0:
        return fr[:(nrow - 1)]
    else:
        return fr

fr = fr.groupby("fruitname").apply(remove_last_odd_row).reset_index(drop=True)

我對熊貓不是很熟悉,但這是一個答案。

for fruit in pd.unique(df.fruitname):
    df1=df[df.fruitname==fruit]
    if len(df1)%2 == 1:
        df=df.drop(df1.last_valid_index())

暫無
暫無

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

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