Как добавить строки в фреймворк pandas в цикле for?

У меня есть цикл for:

for i in links:
     data = urllib2.urlopen(str(i)).read()
     data = json.loads(data)
     data = pd.DataFrame(data.items())
     data = data.transpose()
     data.columns = data.iloc[0]
     data = data.drop(data.index[[0]])

Каждый созданный таким образом кадр данных имеет большинство столбцов вместе с другими, но не все из них. Более того, все они имеют только один ряд. Я должен добавить к кадру данных все отдельные столбцы и каждую строку из каждого фрейма данных, созданного циклом for

Я попробовал pandas конкатенацию или подобное, но ничего не работало. Есть идеи? Спасибо.

Ответы

Ответ 1

Предположим, что ваши данные выглядят следующим образом:

import pandas as pd
import numpy as np

np.random.seed(2015)
df = pd.DataFrame([])
for i in range(5):
    data = dict(zip(np.random.choice(10, replace=False, size=5),
                    np.random.randint(10, size=5)))
    data = pd.DataFrame(data.items())
    data = data.transpose()
    data.columns = data.iloc[0]
    data = data.drop(data.index[[0]])
    df = df.append(data)
print('{}\n'.format(df))
# 0   0   1   2   3   4   5   6   7   8   9
# 1   6 NaN NaN   8   5 NaN NaN   7   0 NaN
# 1 NaN   9   6 NaN   2 NaN   1 NaN NaN   2
# 1 NaN   2   2   1   2 NaN   1 NaN NaN NaN
# 1   6 NaN   6 NaN   4   4   0 NaN NaN NaN
# 1 NaN   9 NaN   9 NaN   7   1   9 NaN NaN

Затем его можно заменить на

np.random.seed(2015)
data = []
for i in range(5):
    data.append(dict(zip(np.random.choice(10, replace=False, size=5),
                         np.random.randint(10, size=5))))
df = pd.DataFrame(data)
print(df)

Другими словами, не создавайте новый DataFrame для каждой строки. Вместо этого, собрать все данные в списке dicts, а затем вызвать df = pd.DataFrame(data) один раз в конце, вне цикла.

Каждый вызов df.append требует выделения пространства для нового DataFrame с одной дополнительной строкой, копирования всех данных из исходного DataFrame в новый DataFrame и последующего копирования данных в новую строку. Все, что распределение и копирование делает вызов df.append в цикле очень неэффективным. Временная стоимость копирования растет квадратично с количеством строк. Не только код "Код-DataFrame-Once" легче писать, но и производительность будет намного лучше - временная стоимость копирования растет линейно с количеством строк.

Ответ 2

Есть две причины, по которым вы можете добавить строки в цикле: 1. добавить к существующему df и 2. создать новый df.

чтобы создать новый df, я думаю, что его хорошо документировано, что вы должны либо создать свои данные в виде списка, а затем создать фрейм данных:

cols = ['c1', 'c2', 'c3']
lst = []
for a in range(2):
    lst.append([1, 2, 3])
df1 = pd.DataFrame(lst, columns=cols)
df1
Out[3]: 
   c1  c2  c3
0   1   2   3
1   1   2   3

ИЛИ, Создайте фрейм с индексом и добавьте к нему

cols = ['c1', 'c2', 'c3']
df2 = pd.DataFrame(columns=cols, index=range(2))
for a in range(2):
    df2.loc[a].c1 = 4
    df2.loc[a].c2 = 5
    df2.loc[a].c3 = 6
df2
Out[4]: 
  c1 c2 c3
0  4  5  6
1  4  5  6

Если вы хотите добавить к существующему фреймворку данных, вы можете использовать один из методов выше, а затем добавить df вместе (с индексом или без него):

df3 = df2.append(df1, ignore_index=True)
df3
Out[6]: 
  c1 c2 c3
0  4  5  6
1  4  5  6
2  1  2  3
3  1  2  3

Или вы также можете создать список записей в словаре и добавить те, что указаны в ответе выше.

lst_dict = []
for a in range(2):
    lst_dict.append({'c1':2, 'c2':2, 'c3': 3})
df4 = df1.append(lst_dict)
df4
Out[7]: 
   c1  c2  c3
0   1   2   3
1   1   2   3
0   2   2   3
1   2   2   3

Использование dict (zip (cols, vals)))

lst_dict = []
for a in range(2):
    vals = [7, 8, 9]
    lst_dict.append(dict(zip(cols, vals)))
df5 = df1.append(lst_dict)

Ответ 3

Я создал кадр данных в цикле for с помощью временного пустого кадра данных. Потому что для каждой итерации цикла for создается новый кадр данных, тем самым перезаписывая содержимое предыдущей итерации.

Следовательно, мне нужно переместить содержимое фрейма данных в пустой кадр данных, который был создан уже. Это так просто. Нам просто нужно использовать функцию .append, как показано ниже:

temp_df = pd.DataFrame() #Temporary empty dataframe
for sent in Sentences:
    New_df = pd.DataFrame({'words': sent.words}) #Creates a new dataframe and contains tokenized words of input sentences
    temp_df = temp_df.append(New_df, ignore_index=True) #Moving the contents of newly created dataframe to the temporary dataframe

За пределами цикла for вы можете скопировать содержимое временного фрейма данных в кадр основных данных, а затем удалить временный фрейм данных, если он вам не нужен.