Pandas DataFrame до списку


115

Перетворити список списків у рамку даних панди легко:

import pandas as pd
df = pd.DataFrame([[1,2,3],[3,4,5]])

Але як повернути df до списку списків?

lol = df.what_to_do_now?
print lol
# [[1,2,3],[3,4,5]]

Відповіді:


177

Ви можете отримати доступ до основного масиву та викликати його tolistметод:

>>> df = pd.DataFrame([[1,2,3],[3,4,5]])
>>> lol = df.values.tolist()
>>> lol
[[1L, 2L, 3L], [3L, 4L, 5L]]

Чому Lв вихідному файлі додаються s?
Kunal Вяс

1
L означає довгий, на відміну від int.
user48956


1
ПРИМІТКА. Це не зберігає впорядкованість стовпців. тож стежте за цим
Рассел Лего

3
Немає жодної причини, яка б не зберегла впорядкування стовпців.
Йохан Обадія

15

Якщо дані мають мітки стовпців та індексів, які ви хочете зберегти, є кілька варіантів.

Приклад даних:

>>> df = pd.DataFrame([[1,2,3],[3,4,5]], \
       columns=('first', 'second', 'third'), \
       index=('alpha', 'beta')) 
>>> df
       first  second  third
alpha      1       2      3
beta       3       4      5

tolist()Описано в інших відповідях метод корисний , але дає тільки основні дані - які не можуть бути досить, в залежності від ваших потреб.

>>> df.values.tolist()
[[1, 2, 3], [3, 4, 5]]

Один із підходів - це перетворити DataFrameна json за допомогою, df.to_json()а потім знову його розібрати. Це громіздко, але має деякі переваги, оскільки to_json()метод має деякі корисні варіанти.

>>> df.to_json()
{
  "first":{"alpha":1,"beta":3},
  "second":{"alpha":2,"beta":4},"third":{"alpha":3,"beta":5}
}

>>> df.to_json(orient='split')
{
 "columns":["first","second","third"],
 "index":["alpha","beta"],
 "data":[[1,2,3],[3,4,5]]
}

Громіздкий, але може бути корисним.

Хороша новина полягає в тому, що складати списки для стовпців і рядків досить просто:

>>> columns = [df.index.name] + [i for i in df.columns]
>>> rows = [[i for i in row] for row in df.itertuples()]

Це дає:

>>> print(f"columns: {columns}\nrows: {rows}") 
columns: [None, 'first', 'second', 'third']
rows: [['alpha', 1, 2, 3], ['beta', 3, 4, 5]]

Якщо Noneяк ім'я індексу турбує, перейменуйте його:

df = df.rename_axis('stage')

Тоді:

>>> columns = [df.index.name] + [i for i in df.columns]
>>> print(f"columns: {columns}\nrows: {rows}") 

columns: ['stage', 'first', 'second', 'third']
rows: [['alpha', 1, 2, 3], ['beta', 3, 4, 5]]

1
Якщо у вас є багаторівневий індекс, то індексний кортеж буде першим елементом згенерованих рядків. Вам знадобиться подальший крок, щоб розділити його.
Костянтин

Чи не було б простіше використовувати DataFrame.itertuples()або DataFrame.to_records()для всього цього?
AMC

@AMC Можливо, я не знаю, можливо? Замість того, щоб понтифікат, чому б не додати належного трактування цієї думки у власній відповіді?
Андрій Е

@AndrewE Так, все-таки варто обговорити та покращити існуючі відповіді.
AMC

5

Я не знаю, чи відповідає це вашим потребам, але ви також можете зробити:

>>> lol = df.values
>>> lol
array([[1, 2, 3],
       [3, 4, 5]])

Це лише нумерований масив з модуля ndarray, який дозволяє виконувати всі звичні речі з масивом numpy.


1
Плюс 1. На практиці часто не потрібно перетворювати масив NumPy у список списків.
jpp

5

Я хотів зберегти індекс, тому адаптував оригінальну відповідь до цього рішення:

list_df = df.reset_index().values.tolist()

Тепер ви можете вставити його десь в іншому місці (наприклад, вставити запитання про переповнення стека) і остаточно відтворити його:

pd.Dataframe(list_df, columns=['name1', ...])
pd.set_index(['name1'], inplace=True)

2

Можливо, щось змінилося, але це повернуло список ndarrays, які зробили те, що мені потрібно.

list(df.values)

1

Примітка: Я спостерігав багато випадків переповнення стека, коли перетворення серії Pandas або DataFrame в масив NumPy або звичайні списки Python абсолютно не потрібно. Якщо ви не новачок у бібліотеці, подумайте, чи перевірте, чи потрібна функціональність вже запропонована тими об’єктами Pandas.

Щоб процитувати коментар від @jpp:

На практиці часто не потрібно перетворювати масив NumPy у список списків.


Якщо Pandas DataFrame / Series не працюватиме, ви можете використовувати вбудовані DataFrame.to_numpyта Series.to_numpyметоди.


1
Ця відповідь означає трохи більше, ніж ваші власні переконання. І, чесно кажучи, це трохи бентежить. Існують цілком поважні причини перетворення фрейму даних у список / масив, просунутий користувач, безумовно, знає.
Ніколя Жерве

@NicolasGervais Це може бути занадто багато, так, я редагую це, щоб узагальнити менше. Є цілком вагомі причини перетворення фрейму даних у список / масив Звичайно, моя відповідь насправді нічого не говорить протилежне. досвідчений користувач, безумовно, знає. Я не бачу сенсу цього удару. Я написав цю відповідь, помітивши, що багато людей перетворюють серії в ndarrays або списки, а ndarrays у списки, просто тому, що вони не знали, які операції підтримують ці об'єкти.
AMC

Я маю на увазі дуже кричущі випадки, як, наприклад, робити, for elem in some_series.values.tolist():оскільки вони не знають, що ви можете перебрати елементи серії. Я не впевнений, що таке жахливе у цій відповіді.
AMC

0

Це дуже просто:

import numpy as np

list_of_lists = np.array(df)

Чим це відрізняється від використання DataFrame.valuesабо DataFrame.to_numpy()? Не забувайте про те, що він створює масив NumPy, а не простий список Python.
AMC

-1

Ми можемо використовувати функцію DataFrame.iterrow () для перегляду кожного з рядків даного Dataframe та побудови списку з даних кожного ряду:

# Empty list 
row_list =[] 

# Iterate over each row 
for index, rows in df.iterrows(): 
    # Create list for the current row 
    my_list =[rows.Date, rows.Event, rows.Cost] 

    # append the list to the final list 
    row_list.append(my_list) 

# Print 
print(row_list) 

Ми можемо успішно витягти кожен рядок даного кадру даних у список


Це не гарна ідея, намагайтеся уникати використання df.iterrow, оскільки це анти-шаблон і повільно, коли df стає великим: stackoverflow.com/questions/16476924/…
Дерек O
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.