2013-08-01 14 views
8

Mam problem z modyfikacją wartości w ramce danych. Chciałbym również poradzić się w sprawie problemu, który muszę rozwiązać, i właściwego sposobu wykorzystania pand, aby go rozwiązać. Będę wdzięczny za pomoc w obu przypadkach. Mam plik zawierający informacje o dopasowaniu poziomu plików audio do głośników. Plik wygląda mniej więcej tak:Zmienianie wartości w pandach Dataframe doenst work

wave_path spk_name spk_example# score mark comments isUsed 
190 122_65_02.04.51.800.wav  idoD idoD 88 NaN  NaN  False 
191 121_110_20.17.27.400.wav idoD idoD 87 NaN  NaN  False 
192 121_111_00.34.57.300.wav idoD idoD 87 NaN  NaN  False 
193 103_31_18.59.12.800.wav  idoD idoD_0 99 HIT  VP False 
194 131_101_02.08.06.500.wav idoD idoD_0 96 HIT  VP False 

To, co muszę zrobić, to rodzaj wyrafinowanego liczenia. Muszę pogrupować wyniki przez głośnik i obliczyć dla każdego głośnika jakieś obliczenia. Następnie kontynuuję pracę z głośnikiem, który wykonał dla mnie najlepsze obliczenia, ale przed kontynuowaniem muszę zaznaczyć wszystkie pliki, których użyłem do obliczeń jako używane, tj. Zmienić wartość isUsed dla każdego wiersza, w którym się pojawiają (mogą się pojawić pliki więcej niż jeden raz) na PRAWDA. Potem robię kolejną iterację. Obliczyć dla każdego głośnika, oznaczyć używane pliki i tak dalej, aż nie będzie już więcej głośników do obliczenia.

Pomyślałem dużo o tym, jak zaimplementować ten proces za pomocą pand (jest to dość łatwe do wdrożenia w zwykłym pythonie, ale zajmie dużo pętli i struktur danych, co moim zdaniem znacznie spowolni proces, a także używałem tego procesu, aby głębiej poznać zdolności pandy)

Wyszedłem z następującym rozwiązaniem. W ramach kroków przygotowawczych pogrupuję według nazwisk i ustawię nazwę pliku jako indeks według metody set_index. Następnie wykonam iterację nad groupbyObj i zastosuję funkcję obliczeniową, która zwróci wybrany głośnik i pliki, które mają być oznaczone jako używane.

Potem będę sprawdzać pliki i oznaczać je jako używane (będzie to szybkie i proste, ponieważ wcześniej ustawię je jako indeksy) i tak dalej, aż skończę obliczenia.

Po pierwsze, nie jestem pewien co do tego rozwiązania, więc możesz mi powiedzieć swoje przemyślenia na ten temat. Teraz próbowałem wykonawczych to i dostał w kłopoty:

Najpierw indeksowany według nazwy pliku, nie ma problemu tutaj:

In [53]: 

    marked_results['isUsed'] = False 
    ind_res = marked_results.set_index('wave_path') 
    ind_res.head() 

Out[53]: 
    spk_name spk_example# score mark comments isUsed 
    wave_path      
    103_31_18.59.12.800.wav  idoD idoD 99 HIT  VP False 
    131_101_02.08.06.500.wav  idoD idoD 99 HIT  VP False 
    144_35_22.46.38.700.wav  idoD idoD 96 HIT  VP False 
    41_09_17.10.11.700.wav  idoD idoD 93 HIT  TEST False 
    122_188_03.19.20.400.wav  idoD idoD 93 NaN  NaN  False 

Potem wybrać plik i sprawdził, że dostanę odpowiednie wpisy do tego pliku:

In [54]: 

    example_file = ind_res.index[0]; 
    ind_res.ix[example_file] 

Out[54]: 
    spk_name spk_example# score mark comments isUsed 
    wave_path      
    103_31_18.59.12.800.wav idoD idoD 99 HIT  VP False 
    103_31_18.59.12.800.wav idoD idoD_0 99 HIT  VP False 
    103_31_18.59.12.800.wav idoD idoD_1 97 HIT  VP False 
    103_31_18.59.12.800.wav idoD idoD_2 95 HIT  VP False 

Teraz także problemy. Potem próbowałem zmienić isused wartość dla tego pliku na True, a gdzie mam problem:

In [56]: 

    ind_res.ix[example_file]['isUsed'] = True 
    ind_res.ix[example_file].isUsed = True 
    ind_res.ix[example_file] 
Out[56]: 
    spk_name spk_example# score mark comments isUsed 
    wave_path      
    103_31_18.59.12.800.wav idoD idoD 99 HIT  VP False 
    103_31_18.59.12.800.wav idoD idoD_0 99 HIT  VP False 
    103_31_18.59.12.800.wav idoD idoD_1 97 HIT  VP False 
    103_31_18.59.12.800.wav idoD idoD_2 95 HIT  VP False 

Więc widać problem. Nic się nie zmieniło. Co ja robię źle? Czy problem opisany powyżej powinien zostać rozwiązany przy użyciu pand?

A także: 1. W jaki sposób mogę podejść do określonej grupy przez obiekt groupby? bcz Myślałem, że może zamiast ustawiać pliki jako indeksowane, grupować według pliku i używać tej grupy przez obj, aby zastosować funkcję zmieniającą do wszystkich jej wystąpień. Ale nie znalazłem sposobu, aby podejść do konkretnej grupy i przekazać nazwę grupy jako parametr i wywołać zastosowanie do wszystkich grup, a następnie działanie tylko na jednym z nich wydawało mi się nie "właściwe".

Mam nadzieję, że to nie jest długa ... :)

+0

jesteś modyfikując kopię, tym '' .IX [example_file 'isused'] '' zobaczyć tutaj: http: // pandas.pydata.org/pandas-docs/dev/indexing.html#returning-a-view-versus-a-kopia – Jeff

Odpowiedz

17

indeksowania obiekty Panda może zwrócić dwa fundamentalnie różne przedmioty: widok lub kopię.

Jeśli mask jest podstawowym kawałek, potem df.ix[mask] zwraca widok z df. Widoki dzielą te same podstawowe dane, co oryginalny obiekt (df). Więc modyfikowanie widoku modyfikuje również oryginalny obiekt.

Jeśli mask jest coś bardziej skomplikowane, takie jak dowolnej kolejności indeksów, następnie df.ix[mask] zwraca kopię niektórych wierszy w df. Modyfikowanie kopii nie ma wpływu na oryginał.

W twoim przypadku, ponieważ wiersze, które mają takie same wave_path występują w dowolnych lokalizacjach, ind_res.ix[example_file] zwraca kopię. Tak więc

ind_res.ix[example_file]['isUsed'] = True 

nie ma wpływu na ind_res.

Zamiast tego można użyć

ind_res.ix[example_file, 'isUsed'] = True 

zmodyfikować ind_res. Jednak poniżej znajdziesz propozycję, która według mnie może być bliższa temu, czego naprawdę chcesz.

Jeff już pod warunkiem link to the Pandas docs która głosi, że

Zasady dotyczące gdy zwracana jest widok na danych są całkowicie zależne od NumPy .

Tutaj są (skomplikowane) rules which describe when a view or copy is returned. Zasadniczo jednak reguła jest taka, że ​​jeśli indeks żąda regularnie rozmieszczonego segmentu tablicy bazowej, zwracany jest widok, w przeciwnym razie zwracana jest kopia (z konieczności).


Oto prosty przykład, który wykorzystuje podstawowy plaster. Widok jest zwracany przez df.ix, a więc zmieniają subdf modyfikuje df jak:

import pandas as pd 
import numpy as np 

df = pd.DataFrame(np.arange(12).reshape(4,3), 
     columns=list('ABC'), index=[0,1,2,3]) 

subdf = df.ix[0] 
print(subdf.values) 
# [0 1 2] 
subdf.values[0] = 100 
print(subdf) 
# A 100 
# B  1 
# C  2 
# Name: 0, dtype: int32 

print(df)   # df is modified 
#  A B C 
# 0 100 1 2 
# 1 3 4 5 
# 2 6 7 8 
# 3 9 10 11 

tutaj prosty przykład wykorzystujący „Indeksowanie” (ozdobnego dowolnych wybranych rzędów). Kopia jest zwracana przez df.ix. Tak więc zmiana subdf nie wpływa na df.

df = pd.DataFrame(np.arange(12).reshape(4,3), 
     columns=list('ABC'), index=[0,1,0,3]) 

subdf = df.ix[0] 
print(subdf.values) 
# [[0 1 2] 
# [6 7 8]] 

subdf.values[0] = 100 
print(subdf) 
#  A B C 
# 0 100 100 100 
# 0 6 7 8 

print(df)   # df is NOT modified 
# A B C 
# 0 0 1 2 
# 1 3 4 5 
# 0 6 7 8 
# 3 9 10 11 

Wskazówki jedyną różnicą pomiędzy tymi dwoma przykładami jest to, że w pierwszym, w którym jest zwrócone w widoku indeks w [0,1,2,3], podczas gdy w drugim, gdzie jest zawracany kopię wskaźnik wynosił [0,1,0,3].

Ponieważ jesteśmy wybranymi wierszami, gdzie indeks wynosi 0, w pierwszym przykładzie możemy to zrobić z podstawowym plasterkiem. W drugim przykładzie wiersze, w których indeks jest równy 0, mogą pojawić się w dowolnych lokalizacjach, więc należy zwrócić kopię.


Pomimo ranted na temat subtelności Pandy/NumPy krojenie, ja naprawdę nie sądzę, że

ind_res.ix[example_file, 'isUsed'] = True 

jest to, czego ostatecznie szukasz. Prawdopodobnie chcesz zrobić coś bardziej jak

import pandas as pd 
import numpy as np 

df = pd.DataFrame(np.arange(12).reshape(4,3), 
        columns=list('ABC')) 
df['A'] = df['A']%2 
print(df) 
# A B C 
# 0 0 1 2 
# 1 1 4 5 
# 2 0 7 8 
# 3 1 10 11 

def calculation(grp): 
    grp['C'] = True 
    return grp 

newdf = df.groupby('A').apply(calculation) 
print(newdf) 

co daje

A B  C 
0 0 1 True 
1 1 4 True 
2 0 7 True 
3 1 10 True 
+1

Dzięki za wyjaśnienie. Uważam, że to dość denerwujące, nie mogąc z góry powiedzieć, czy źle widzę, czy kopię wcześniej. To kiepski projekt dla mojego gustu. Jeśli chodzi o twoją ostatnią sugestię, problem polega na tym, że niektóre pliki pojawiają się w więcej niż jednej grupie. więc muszę znaleźć wszystkie dodatki we wszystkich grupach i zmodyfikować je wszystkie. Zamiast tego wybieram indeksowanie plików z wyprzedzeniem i zmieniam wszystkie wyszukiwania w jednym ujęciu. Jeśli nadal sądzisz, że jest lepszy sposób na zrobienie tego, z przyjemnością posłucham. Czy możesz mi powiedzieć, czy też mogę uzyskać grupę konkretnie pod swoją nazwą z obiektu groupby? Wielkie dzięki! – idoda

+0

Propozycja użycia groupby nie działa. Kolumna "isUsed" jest zmieniana wewnątrz funkcji "obliczeniowej", ale zewnętrzna ramka danych się nie zmienia. Wiesz dlaczego? czy to możliwe, że ta grupa to także kopie DF? @unut – idoda

+0

Sugestia użycia groupby nie działa. Kolumna "isUsed" jest zmieniana wewnątrz funkcji "obliczeniowej", ale zewnętrzna ramka danych się nie zmienia. Wiesz dlaczego? czy to możliwe, że ta grupa to także kopie DF? – idoda

Powiązane problemy