2015-10-15 173 views
7

我有一個熊貓據幀,這樣的:蟒蛇大熊貓據幀:刪除選定的行

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 

我想刪除最後一個條目,每果,如果水果有條目的奇(不均勻)號( %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循環?我一直在Google上搜索4天,但無法弄清楚如何做到這一點。

回答

1

你可以使用應用功能:

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) 
6

使用value_counts確定每個水果的物品數量,並根據是否有奇數編號建立它們的列表。 我們可以通過使用%模運算符來生成一個10,使用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) 
0

我對熊貓不是很熟悉,但他重新回答。

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

的另一種方法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 
+0

你很狡猾;)+1 – EdChum