Czy można dodać metainformacje / metadane do pandy DataFrame?
Na przykład nazwa instrumentu używanego do pomiaru danych, odpowiedzialny instrument itp.
Jednym obejściem byłoby utworzenie kolumny z tymi informacjami, ale przechowywanie pojedynczej informacji w każdym wierszu wydaje się marnotrawstwem!
Odpowiedzi:
Oczywiście, podobnie jak większość obiektów Pythona, możesz dołączyć nowe atrybuty do
pandas.DataFrame
:import pandas as pd df = pd.DataFrame([]) df.instrument_name = 'Binky'
Należy jednak pamiętać, że podczas gdy można dołączyć atrybuty do DataFrame, operacje wykonywane na DataFrame (takich jak
groupby
,pivot
,join
lubloc
, aby wymienić tylko kilka) może powrócić nową DataFrame bez metadanych załączeniu. Pandy nie mają jeszcze solidnej metody propagowania metadanych dołączonych do ramek DataFrames .Możliwe jest zachowanie metadanych w pliku . Przykład przechowywania metadanych w pliku HDF5 można znaleźć tutaj .
źródło
store = pd.HDFStore(...)
, atrybuty mogą być przechowywane zstore.root._v_attrs.key = value
.df = pd.DataFrame(); df.meta = {}
ProdukujeUserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access
). (Brak ostrzeżenia, jeśli atrybut został już utworzony jak wdf = pd.DataFrame(); df.meta = ''; df.meta = {}
).Właśnie napotkałem ten problem. Począwszy od pandy 0.13, ramki DataFrames mają atrybut _metadata, który jest trwały przez funkcje zwracające nowe ramki DataFrames. Wydaje się również, że serializacja jest w porządku (próbowałem tylko json, ale wyobrażam sobie, że hdf jest również objęty).
źródło
_metadata
nie jest częścią publicznego API, więc zdecydowanie odradzam poleganie na tej funkcjonalności..attrs
jest częścią interfejsu API xray)_metadata
jest w rzeczywistości atrybutem klasy, a nie atrybutem instancji. Tak więc noweDataFrame
instancje dziedziczą po poprzednich, o ile moduł pozostaje załadowany. Nie używaj_metadata
do niczego. +1 dlaxarray
!Nie całkiem. Chociaż można dodać atrybuty zawierające metadane do klasy DataFrame, o czym wspomina @unutbu, wiele metod DataFrame zwraca nową ramkę DataFrame, więc metadane zostałyby utracone. Jeśli musisz manipulować ramką danych, najlepszym rozwiązaniem byłoby umieszczenie metadanych i ramki DataFrame w innej klasie. Zobacz tę dyskusję na GitHub: https://github.com/pydata/pandas/issues/2485
Obecnie istnieje otwarte żądanie ściągnięcia, aby dodać obiekt MetaDataFrame, który lepiej obsługiwałby metadane.
źródło
Począwszy od pandy 1.0, prawdopodobnie wcześniej, istnieje teraz
Dataframe.attrs
właściwość. Jest eksperymentalny, ale prawdopodobnie tego będziesz chciał w przyszłości. Na przykład:import pandas as pd df = pd.DataFrame([]) df.attrs['instrument_name'] = 'Binky'
Znajdź to w dokumentach tutaj .
Wypróbowanie tego z
to_parquet
a potemfrom_parquet
wydaje się nie utrzymywać się, więc upewnij się, że sprawdziłeś to w swoim przypadku użycia.źródło
dataclass
dla metadanych, a następnie podklasy,DataFrame
aby mieć metodę wykonującą ładowanie / zrzucanie, jak w udostępnionym poście, może być dobrym rozwiązaniem.Najlepsza odpowiedź dotycząca dołączania dowolnych atrybutów do obiektu DataFrame jest dobra, ale jeśli używasz słownika, listy lub krotki, wyemituje błąd „Pandy nie pozwalają na tworzenie kolumn za pomocą nowej nazwy atrybutu”. Poniższe rozwiązanie działa w przypadku przechowywania dowolnych atrybutów.
from types import SimpleNamespace df = pd.DataFrame() df.meta = SimpleNamespace() df.meta.foo = [1,2,3]
źródło
pd.DataFrame._metadata += ["meta"]
. Zwróć uwagę, że ta część jest atrybutem Pand, a nie atrybutem konkretnej ramki danychdf.meta
wyzwala ostrzeżenie, że Pandy nie pozwalają na generowanie nowych kolumn w ten sposób.df.meta
jest to SimpleNamespace. Pandy nie będą próbowały zbudować z niego kolumny.Jak wspomniano w innych odpowiedziach i komentarzach,
_metadata
nie jest częścią publicznego API, więc zdecydowanie nie jest dobrym pomysłem używanie go w środowisku produkcyjnym. Ale nadal możesz chcieć użyć go w prototypowaniu badawczym i zastąpić go, jeśli przestanie działać. Teraz działa zgroupby
/apply
, co jest pomocne. Oto przykład (którego nie mogłem znaleźć w innych odpowiedziach):df = pd.DataFrame([1, 2, 2, 3, 3], columns=['val']) df.my_attribute = "my_value" df._metadata.append('my_attribute') df.groupby('val').apply(lambda group: group.my_attribute)
Wynik:
val 1 my_value 2 my_value 3 my_value dtype: object
źródło
Dochodząc do tego dość późno, pomyślałem, że może to być pomocne, jeśli potrzebujesz metadanych, aby przetrwać we / wy. Jest stosunkowo nowy pakiet o nazwie h5io, którego używałem , aby to osiągnąć.
Powinien umożliwić szybki odczyt / zapis z HDF5 dla kilku popularnych formatów, z których jeden to ramka danych. Możesz więc na przykład umieścić ramkę danych w słowniku i dołączyć metadane jako pola w słowniku. Na przykład:
save_dict = dict(data=my_df, name='chris', record_date='1/1/2016') h5io.write_hdf5('path/to/file.hdf5', save_dict) in_data = h5io.read_hdf5('path/to/file.hdf5') df = in_data['data'] name = in_data['name'] etc...
Inną opcją byłoby przyjrzenie się projektowi, takim jak xray , który jest pod pewnymi względami bardziej złożony, ale myślę, że pozwala na użycie metadanych i jest dość łatwy do przekonwertowania na ramkę DataFrame.
źródło
Jak wspomniał @choldgraf, stwierdziłem, że xarray jest doskonałym narzędziem do dołączania metadanych podczas porównywania danych i wykreślania wyników między kilkoma ramkami danych.
W mojej pracy często porównujemy wyniki kilku wersji oprogramowania sprzętowego i różnych scenariuszy testowych, a dodanie tych informacji jest tak proste:
df = pd.read_csv(meaningless_test) metadata = {'fw': foo, 'test_name': bar, 'scenario': sc_01} ds = xr.Dataset.from_dataframe(df) ds.attrs = metadata
źródło
Szukałem rozwiązania i stwierdziłem, że rama pandy ma tę właściwość
attrs
pd.DataFrame().attrs.update({'your_attribute' : 'value'}) frame.attrs['your_attribute']
Ten atrybut będzie zawsze trzymał się twojej ramki, gdy go miniesz!
źródło
Miałem ten sam problem i zastosowałem obejście polegające na utworzeniu nowego, mniejszego DF ze słownika z metadanymi:
meta = {"name": "Sample Dataframe", "Created": "19/07/2019"} dfMeta = pd.DataFrame.from_dict(meta, orient='index')
Ten plik dfMeta można następnie zapisać wraz z oryginalnym DF w marynacie itp
Zobacz Zapisywanie i ładowanie wielu obiektów w pliku marynaty? (Odpowiedź Lutza) za doskonałą odpowiedź na temat zapisywania i pobierania wielu ramek danych za pomocą pikle
źródło