2016-06-19 40 views
6

Say mam następujący dataframe i chcę, aby zmienić dwa elementy w kolumnie c które odpowiadają dwóch pierwszych elementów w kolumnie a które są równe 1 równa 2.Zastosowanie loc i iloc razem w pand

>>> df = pd.DataFrame({"a" : [1,1,1,1,2,2,2,2], "b" : [2,3,1,4,5,6,7,2], "c" : [1,2,3,4,5,6,7,8]}) 
>>> df.loc[df["a"] == 1, "c"].iloc[0:2] = 2 
>>> df 
    a b c 
0 1 2 1 
1 1 3 2 
2 1 1 3 
3 1 4 4 
4 2 5 5 
5 2 6 6 
6 2 7 7 
7 2 2 8 

Kod w drugiej linii nie działa, ponieważ iloc zestawy kopii, więc oryginalny dataframe nie jest modyfikowany. Jak to zrobić?

Odpowiedz

2

Można użyć Index.isin:

import pandas as pd 

df = pd.DataFrame({"a" : [1,1,1,1,2,2,2,2], 
        "b" : [2,3,1,4,5,6,7,2], 
        "c" : [1,2,3,4,5,6,7,8]}) 

#more general index      
df.index = df.index + 10 
print (df) 
    a b c 
10 1 2 1 
11 1 3 2 
12 1 1 3 
13 1 4 4 
14 2 5 5 
15 2 6 6 
16 2 7 7 
17 2 2 8 

print (df.index.isin(df.index[:2])) 
[ True True False False False False False False] 

df.loc[(df["a"] == 1) & (df.index.isin(df.index[:2])), "c"] = 2 
print (df) 
    a b c 
10 1 2 2 
11 1 3 2 
12 1 1 3 
13 1 4 4 
14 2 5 5 
15 2 6 6 
16 2 7 7 
17 2 2 8 

Jeśli indeks jest nice (zaczyna się od 0 bez duplikatów):

df.loc[(df["a"] == 1) & (df.index < 2), "c"] = 2 
print (df) 
    a b c 
0 1 2 2 
1 1 3 2 
2 1 1 3 
3 1 4 4 
4 2 5 5 
5 2 6 6 
6 2 7 7 
7 2 2 8 

Innym rozwiązaniem:

mask = df["a"] == 1 
mask = mask & (mask.cumsum() < 3) 

df.loc[mask.index[:2], "c"] = 2 
print (df) 
    a b c 
0 1 2 2 
1 1 3 2 
2 1 1 3 
3 1 4 4 
4 2 5 5 
5 2 6 6 
6 2 7 7 
7 2 2 8 
4

Brudny sposobem byłoby :

df.loc[df[df['a']==1][:2].index, 'c'] = 2 
+1

Nie sądzę, że to jest brudne! Jest to przykład klasy krojenia, w której jest pozycjonowana wzdłuż jednej osi, a według indeksu z drugiej. – piRSquared

+1

Udało mi się zapisać jeden znak: 'df.loc [df.index [df.a == 1] [: 2], 'c'] = 2' – piRSquared

+0

@piRSquared Generalnie nie podoba mi się powtórzenie w' df [df [col] == some_value] 'składnia i tutaj staje się' df [df [df [... ... Dlatego nazwałem to brudne. :) – ayhan