2015-10-20 9 views
5

Mam dataframe, który wygląda tak:if dla dataframes panda w Pythonie

timestamp      0   1   2   3           
2013-04-17 05:00:00  4.335212 2655.140854 2655.140854 2655.140854 
2013-04-17 05:10:00  2.224966 2655.140854 2655.140854 2655.140854 
2013-04-17 05:20:00  2.409150 2655.140854 2655.140854 2655.140854 
2013-04-17 05:30:00 2655.140854 2655.140854 2655.140854 2655.140854 

muszę nałożyć if kryteria oświadczenie o każdej wartości w dataframe, próbowałem za pomocą:

dirt = dirt.astype(float) 
for ind, i in enumerate(dirt): 
    if i < 0: 
     dirt[ind] = i + 360 
    if i > 360: 
     dirt[ind] = i - 360 

Jednak dodawanie i odejmowanie nie występuje na żadnej z wartości. Jakieś pomysły?

Odpowiedz

3

Powinieneś użyć .iterrows() zamiast enumerate(df). Gdy wykonasz enumerate(df), otrzymasz po prostu nazwy kolumn, które nie spełnią Twojego warunku. iterrows() zwraca indeks i wiersz (jako pandas.Series) w każdej iteracji.

Ale dla Twojego wymagania możesz wykonać iterację ponad df.columns i zrobić to, co chcesz, w sposób wektorowy dla każdej kolumny. Przykład -

for col in df.columns: 
    df.loc[df[col] < 0,col] += 360 
    df.loc[df[col] > 360,col] -= 360 

Używam columns zamiast rows zakładając liczbę kolumn będzie znacznie mniejsza niż liczba wierszy, dlatego będziemy robić faktyczną pętlę o wiele mniej iteracji (i używając vectorized dodatek dla więcej danych jednocześnie).

Demo -

In [128]: df 
Out[128]: 
           0   1   2   3 
timestamp 
2013-04-17 05:00:00  4.335212 2655.140854 2655.140854 2655.140854 
2013-04-17 05:10:00  2.224966 2655.140854 2655.140854 2655.140854 
2013-04-17 05:20:00  2.409150 2655.140854 2655.140854 2655.140854 
2013-04-17 05:30:00 2655.140854 2655.140854 2655.140854 2655.140854 

In [134]: for col in df.columns: 
    .....:  df.loc[df[col] < 0,col] += 360 
    .....:  df.loc[df[col] > 360,col] -= 360 
    .....: 

In [135]: df 
Out[135]: 
           0   1   2   3 
timestamp 
2013-04-17 05:00:00  4.335212 2295.140854 2295.140854 2295.140854 
2013-04-17 05:10:00  2.224966 2295.140854 2295.140854 2295.140854 
2013-04-17 05:20:00  2.409150 2295.140854 2295.140854 2295.140854 
2013-04-17 05:30:00 2295.140854 2295.140854 2295.140854 2295.140854 
3

Można użyć maskowanie z where i update zaktualizować istniejące wartości dataframe tak:

In [188]: df 
Out[188]: 
           0   1   2   3 
timestamp                
2013-04-1705:00:00  4.335212 2655.140854 2655.140854 2655.140854 
2013-04-1705:10:00  2.224966 2655.140854 2655.140854 2655.140854 
2013-04-1705:20:00  2.409150 2655.140854 2655.140854 2655.140854 
2013-04-1705:30:00 2655.140854 2655.140854 2655.140854 2655.140854 

In [189]: df_small = df.where(df < 0).apply(lambda x: x + 360) 

In [190]: df_small 
Out[190]: 
        0 1 2 3 
timestamp       
2013-04-1705:00:00 NaN NaN NaN NaN 
2013-04-1705:10:00 NaN NaN NaN NaN 
2013-04-1705:20:00 NaN NaN NaN NaN 
2013-04-1705:30:00 NaN NaN NaN NaN 

In [191]: df_large = df.where(df > 360).apply(lambda x: x - 360) 

In [192]: df_large 
Out[192]: 
           0   1   2   3 
timestamp                
2013-04-1705:00:00   NaN 2295.140854 2295.140854 2295.140854 
2013-04-1705:10:00   NaN 2295.140854 2295.140854 2295.140854 
2013-04-1705:20:00   NaN 2295.140854 2295.140854 2295.140854 
2013-04-1705:30:00 2295.140854 2295.140854 2295.140854 2295.140854 

In [193]: df.update(df_small) 

In [194]: df.update(df_large) 

In [195]: df 
Out[195]: 
           0   1   2   3 
timestamp                
2013-04-1705:00:00  4.335212 2295.140854 2295.140854 2295.140854 
2013-04-1705:10:00  2.224966 2295.140854 2295.140854 2295.140854 
2013-04-1705:20:00  2.409150 2295.140854 2295.140854 2295.140854 
2013-04-1705:30:00 2295.140854 2295.140854 2295.140854 2295.140854 

Uwaga:

To potencjalnie może zaspokoić przypadki narożne, jeśli masz warunki takie jak: "wartość" < 360 następnie +360 else -360, ale kolejność aktualizacji spowoduje ponowne zastosowanie wyników, tj. 1 + 360 = 361, a następnie 361> 360, więc znów staje się 1.

Ale dla twojego przypadku użycia, myślę, że metoda @ AnandSKumar jest bardzo czysta i bliska temu, czego szukasz.