Я использую pandas dataframe в Python 3.6 для индексирования файлов и атрибутов. Мое первоначальное решение использует имена файлов в первом столбце кадра данных и числовые атрибуты в других столбцах.
Когда я перебираю файлы, собирающие атрибуты, и пытаюсь присвоить значения соответствующему столбцу на фрейме данных, значения не сохраняются должным образом.
Я сделал несколько попыток и, наконец, получил работающий код, но я не понимаю, почему первоначальное решение не сработало.
Может ли кто-нибудь дать какое-то объяснение или, возможно, лучшее решение для присвоения значений элементам в кадре данных, которые не вызывают аварийные сигналы. (Я знаю, как отключить сигнализацию в этом случае, но я бы не стал этого делать)
Проблема иллюстрируется следующим кодом. Я получаю те же результаты, если фрейм данных создается по-разному, а также если столбец со строковым значением находится на разных позициях, например второй или третий столбец на фрейме данных.
Не пытался использовать другие типы данных, такие как bool, но я думаю, что проблема связана с фреймами данных со смешанными типами данных в целом.
#!/usr/bin/python3
# Import standard libraries
import pandas as pd
import numpy as np
# constants used as label for harmonization with the HDF5 ontology used
ROW_LENGTH = 11
COL1 = 'x1'
COL2 = 'x2'
COL3 = 'x3'
def _main():
# Create a dataframe
first_df = pd.DataFrame(columns=[COL1, COL2, COL3])
first_df[COL1] = ["foo"]*ROW_LENGTH
first_df[COL2] = [np.NaN]*ROW_LENGTH
first_df[COL3] = [np.NaN]*ROW_LENGTH
# Go around assigning data
for row in range(ROW_LENGTH):
first_df[COL1][row] = "{}".format(row)
first_df[COL2][row] = row*2 # Although it gives warning, it works
first_df.loc[row][COL3] = row*3 # And this, that should work, don't
print("Although no data was not stored on the third column using: first_df.loc[row][COL3]")
print(first_df.head())
print("\n...I can retrieve the data like: first_df[COL2][5] = '{}'".format(first_df[COL2][3]))
print("... or like that: first_df.loc[5][COL2] = '{}'".format(first_df.loc[3][COL2]))
# If the first row is numeric...
second_df = pd.DataFrame(columns=[COL1, COL2, COL3])
second_df[COL1] = [0.0]*ROW_LENGTH
second_df[COL2] = [0.0]*ROW_LENGTH
second_df[COL3] = [0.0]*ROW_LENGTH
# Go around assigning data
for row in range(ROW_LENGTH):
second_df[COL1][row] = row*1.0
second_df[COL2][row] = row*2.0
second_df.loc[row][COL3] = row*3.0
print("\nNow if I use only numeric columns, everything works as expected:")
print(second_df.head())
if __name__ == '__main__':
_main()
Вывод:
Although no data was not stored on the third column using: first_df.loc[row][COL3]
x1 x2 x3
0 0 0.0 NaN
1 1 2.0 NaN
2 2 4.0 NaN
3 3 6.0 NaN
4 4 8.0 NaN
...I can retrieve the data like: first_df[COL2][5] = '6.0'
... or like that: first_df.loc[5][COL2] = '6.0'
Now if I use only numeric columns, everything works as expected:
x1 x2 x3
0 0.0 0.0 0.0
1 1.0 2.0 3.0
2 2.0 4.0 6.0
3 3.0 6.0 9.0
4 4.0 8.0 12.0
Предупреждающее сообщение такое
./test.py:24: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
first_df[COL2][row] = row*2 # Although it gives warning, it works
Это предупреждение можно отключить, используя: pd.options.mode.chained_assignment = None
Я полагаю, что код самообъяснимо относительно ожидаемых результатов, но вкратце я хотел бы получить доступ к любому элементу, используя метод .loc.