Konstruowanie pand DataFrame z wartości w zmiennych daje „ValueError: Jeśli używasz wszystkich wartości skalarnych, musisz przekazać indeks”

370

To może być proste pytanie, ale nie mogę wymyślić, jak to zrobić. Powiedzmy, że mam dwie zmienne w następujący sposób.

a = 2
b = 3

Chcę zbudować DataFrame z tego:

df2 = pd.DataFrame({'A':a,'B':b})

To generuje błąd:

ValueError: Jeśli używasz wszystkich wartości skalarnych, musisz przekazać indeks

Próbowałem tego także:

df2 = (pd.DataFrame({'a':a,'b':b})).reset_index()

Daje to ten sam komunikat o błędzie.

Nilani Algiriyage
źródło

Odpowiedzi:

570

Komunikat o błędzie mówi, że jeśli przekazujesz wartości skalarne, musisz przekazać indeks. Nie możesz więc użyć wartości skalarnych dla kolumn - np. Użyj listy:

>>> df = pd.DataFrame({'A': [a], 'B': [b]})
>>> df
   A  B
0  2  3

lub użyj wartości skalarnych i przekaż indeks:

>>> df = pd.DataFrame({'A': a, 'B': b}, index=[0])
>>> df
   A  B
0  2  3
DSM
źródło
7
Być może dzieje się tak, ponieważ kolejność elementów na liście w Pythonie jest trwała, podczas gdy kolejność elementów w słowniku nie. Można utworzyć instancję DataFrame z pustym słownikiem. Zasadniczo przypuszczam, że pokazana tutaj jednorzędowa ramka DataFrame mogłaby być również zbudowana ze słownika, ponieważ kolejność nie ma znaczenia (ale nie została zaimplementowana). Jednak w przypadku wielu wierszy Pandy nie byłyby w stanie utworzyć DataFrame, ponieważ nie wiedziałby, które elementy należały do ​​tego samego wiersza.
Alexander
2
@VitalyIsaev - W takim przypadku wiersz ramki danych (reprezentowany przez dany słownik) nie ma indeksu (nawet domyślnego). Prostym rozwiązaniem jest zawinięcie słownika w listę, która ma „naturalne indeksowanie”. Można twierdzić, że jeśli podano tylko jeden słownik (bez listy zawijania), to załóżmy index=0, ale może to prowadzić do przypadkowego niewłaściwego użycia (myśląc, że pojedynczy słownik może w jakiś sposób stworzyć ramkę danych z wieloma wierszami)
Ori
kilka rozwiązań w tym linku eulertech.wordpress.com/2017/11/28/…
Jason Gol
Powodem tego jest to, że DataFrames są przeznaczone do przechowywania danych dwuwymiarowych (tj. Wierszy dwóch zmiennych OP). Jeśli chcesz po prostu trzymać indeks -> pary wartości (jak słownik), powinieneś użyć Serii, jak sugeruje Rob .
Danuker
Jest to ramka danych z pojedynczą próbką / wierszem, więc indeks = [0] ma logiczny sens; ale można również zmanipulować go, aby był indeksem = [100], co działa. P: Czy indeks nie powinien być logicznie porządkowany przyrostowo, dlaczego python pozwala na manipulowanie indeksem?
Sumanth Lazarus
65

Możesz także użyć pd.DataFrame.from_recordswygodniejszego, gdy masz już pod ręką słownik:

df = pd.DataFrame.from_records([{ 'A':a,'B':b }])

Możesz także ustawić indeks, jeśli chcesz:

df = pd.DataFrame.from_records([{ 'A':a,'B':b }], index='A')
faks
źródło
27
Ta odpowiedź nie działa dla mnie - przy użyciu from_records pojawia się ten sam komunikat o błędzie.
Dave Kielpinski
Dave, próbowałeś fragmentu kodu (oczywiście zdefiniuj aib)? Czy nadal pojawia się komunikat o błędzie? Czy możesz pisać?
fAX
12
@DaveKielpinski Czy zapomniałeś dodać nawiasy?
Dennis
Spowoduje to użycie klawiszy dict jako nazw kolumn. Jak ustawić klucze do indeksowania?
mingchau
@DaveKielpinski Sprawdź, czy przekazałeś listę do metody „from_records”; w przeciwnym razie nie będzie działać, a otrzymasz ten sam komunikat o błędzie, jak podczas wywoływania DataFrame w słowniku.
mairan
55

Najpierw musisz utworzyć serię pand. Drugim krokiem jest konwersja serii pand na ramkę danych pand.

import pandas as pd
data = {'a': 1, 'b': 2}
pd.Series(data).to_frame()

Możesz nawet podać nazwę kolumny.

pd.Series(data).to_frame('ColumnName')
MLguy
źródło
1
To zadziałało dla mnie. Mój słownik miał klucze całkowite i wartości ndarray.
StatsSorceress
pd.Series(data).to_frame('ColumnName')jest krótszy, chociaż ten odpowiednik jest być może bardziej bezpośredni:pd.DataFrame.from_dict(data, orient='index', columns=['ColumnName'])
Alex F
29

Możesz spróbować zapakować słownik do listy

my_dict = {'A':1,'B':2}

pd.DataFrame([my_dict])

   A  B
0  1  2
Nowicjusz
źródło
8

Może Series zapewni wszystkie potrzebne funkcje:

pd.Series({'A':a,'B':b})

DataFrame można traktować jako zbiór serii, dlatego możesz:

  • Połącz wiele serii w jedną ramkę danych (jak opisano tutaj )

  • Dodaj zmienną Series do istniejącej ramki danych ( przykład tutaj )

Obrabować
źródło
7

Musisz podać iterowalne wartości dla kolumn Pandas DataFrame:

df2 = pd.DataFrame({'A':[a],'B':[b]})
Ely
źródło
6

Miałem ten sam problem z tablicami numpy i rozwiązaniem jest ich spłaszczenie:

data = {
    'b': array1.flatten(),
    'a': array2.flatten(),
}

df = pd.DataFrame(data)
MicheleDIncecco
źródło
3

Jeśli zamierzasz przekonwertować słownik skalarów, musisz dołączyć indeks:

import pandas as pd

alphabets = {'A': 'a', 'B': 'b'}
index = [0]
alphabets_df = pd.DataFrame(alphabets, index=index)
print(alphabets_df)

Chociaż indeks nie jest wymagany dla słownika list, ten sam pomysł można rozszerzyć na słownik list:

planets = {'planet': ['earth', 'mars', 'jupiter'], 'length_of_day': ['1', '1.03', '0.414']}
index = [0, 1, 2]
planets_df = pd.DataFrame(planets, index=index)
print(planets_df)

Oczywiście w przypadku słownika list można zbudować ramkę danych bez indeksu:

planets_df = pd.DataFrame(planets)
print(planets_df)
k0L1081
źródło
3

Możesz spróbować:

df2 = pd.DataFrame.from_dict({'a':a,'b':b}, orient = 'index')

Z dokumentacji argumentu „orient”: jeśli kluczami przekazanego dict powinny być kolumny wynikowej DataFrame, przekaż „kolumny” (domyślnie). W przeciwnym razie, jeśli klucze powinny być wierszami, należy przekazać „indeks”.

Matthew Connell
źródło
Użyj narzędzi do formatowania, aby poprawnie edytować i sformatować pytanie / odpowiedź. Kody w zdaniach mają być sformatowane jako code Bardzo ważne słowa, aby były pogrubione , mniej ważne kursywa Kursywa W razie potrzeby używaj także list
Morse
To nie rozwiązuje zadanego pytania, daje inny wynik niż pożądany.
Ken Williams
3

Magia pand w pracy. Cała logika jest wyłączona.

Komunikat o błędzie "ValueError: If using all scalar values, you must pass an index"mówi, że musisz przekazać indeks.

Nie musi to oznaczać, że przekazanie indeksu powoduje, że pandy robią to, co chcesz

Po przejściu indeksu pandy będą traktować klucze słownika jako nazwy kolumn, a wartości jak to, co kolumna powinna zawierać dla każdej wartości w indeksie.

a = 2
b = 3
df2 = pd.DataFrame({'A':a,'B':b}, index=[1])

    A   B
1   2   3

Przekazywanie większego indeksu:

df2 = pd.DataFrame({'A':a,'B':b}, index=[1, 2, 3, 4])

    A   B
1   2   3
2   2   3
3   2   3
4   2   3

Indeks jest zwykle generowany automatycznie przez ramkę danych, gdy nie jest podany. Jednak pandy nie wiedzą, ile rzędów 2i 3chcesz. Możesz jednak wyrazić się bardziej otwarcie

df2 = pd.DataFrame({'A':[a]*4,'B':[b]*4})
df2

    A   B
0   2   3
1   2   3
2   2   3
3   2   3

Domyślny indeks wynosi 0.

Podczas tworzenia ramek danych zalecałbym zawsze przekazywanie słownika list do konstruktora ramki danych. Łatwiej jest czytać innym programistom. Panda ma wiele ostrzeżeń, nie zmuszaj innych programistów, by czytali Twój kod.

firelynx
źródło
3

dane wejściowe nie muszą być listą rekordów - może to być także pojedynczy słownik:

pd.DataFrame.from_records({'a':1,'b':2}, index=[0])
   a  b
0  1  2

Co wydaje się równoważne z:

pd.DataFrame({'a':1,'b':2}, index=[0])
   a  b
0  1  2
SV
źródło
2

Wynika to z faktu, że DataFrame ma dwa intuicyjne wymiary - kolumny i wiersze.

Podajesz kolumny tylko przy użyciu kluczy słownika.

Jeśli chcesz określić tylko dane jednowymiarowe, użyj serii!

Danuker
źródło
0

Konwertuj słownik na ramkę danych

col_dict_df = pd.Series(col_dict).to_frame('new_col').reset_index()

Nadaj nową nazwę kolumnie

col_dict_df.columns = ['col1', 'col2']
kamran kausar
źródło
-2

Jeśli masz słownik, możesz przekształcić go w ramkę danych pand za pomocą następującego wiersza kodu:

pd.DataFrame({"key": d.keys(), "value": d.values()})
ingrid
źródło
Działa, ale IMHO nie ma większego sensu <code> `<! - language: lang-py -> fruits_count = defaultdict (int) fruits_count [" apples "] = 10 fruits_count [" bananas "] = 21 pd.DataFrame ({"key": fruits_count.keys (), "value": fruits_count.values ​​()}) Out: wartość klucza 0 (banany, jabłka) (21, 10) 1 (banany, jabłka) (21, 10) <kod>
Emiter
-3

Wystarczy przekazać dyktando na liście:

a = 2
b = 3
df2 = pd.DataFrame([{'A':a,'B':b}])
LeandroHumb
źródło