Эффективен для циклов для Pandas фреймов данных - PullRequest
1 голос
/ 08 июля 2020

У меня есть 2 Pandas Dataframes, X_ol и y_ol, с формой 29000 x 29 и 29000 x 21, и я запускаю вложенный для l oop через эти данные, чтобы генерировать больше данных (как вы ' См. ниже). То, что я пытаюсь достичь с помощью этого для l oop, выглядит примерно так:

    DataFrame X_ol                              DataFrame y_ol
    id     Date      c1      c2      c3         c1      c2      c3
    1      2000      0       1       1          0       1       1
    2      2001      1       0       1          1       0       1
    3      2002      1       1       0          1       1       0
    4      2003      1       1       1          1       1       1

    # (New DataFrame X)                         # (Second New DataFrame, y)
    id     Date      c1      c2      c3         c1      c2      c3 
    1      2000      0       0       1          0       1       0
    1      2000      0       1       0          0       0       1
    2      2001      0       0       1          1       0       0
    2      2001      1       0       0          0       0       1
    3      2002      0       1       0          1       0       0
    3      2002      1       0       0          0       1       0
    4      2003      0       1       1          1       0       0
    4      2003      1       0       1          0       1       0
    4      2003      1       1       0          0       0       1
    

, поэтому он просматривает фрейм данных y_ol строка за строкой и для каждого значения ячейки 1 создает новую строку в кадре данных X, при этом эта ячейка отключена, и создает новую строку в кадре данных y с соответствующей ячейкой, а все другие значения в той же строке в кадре данных y теперь будут отключены. Я написал этот код, который делает это правильно, но занимает так много времени. 12+ минут создания 2 фреймов данных из 60000 строк, есть ли встроенные pandas функции / методы, которые можно использовать, чтобы сделать этот более эффективным или другой метод, полностью исключающий for l oop?

for i in range(len(y_ol)):
    ab = y_ol.iloc[i].where(y_ol.iloc[i]==1)
    abInd = ab[ab==1.0].index
    for j in abInd:
        y_tmp = deepcopy(y_ol.iloc[i:i+1, :])
        y_ol[j][i] = 0
        conc = pd.concat([X_ol.iloc[i:i+1,:], y_ol.iloc[i:i+1, :]], axis=1)
        X = X.append(conc)
        y_tmp.iloc[:, :] = 0
        y_tmp[j] = 1
        y = y.append(y_tmp)
        y_ol[j][i] = 1

Заранее спасибо

Ответы [ 2 ]

1 голос
/ 09 июля 2020

Я бы обработал фреймы данных по столбцам, в которых столбец в y_ol содержит 1, и объединил бы временные фреймы данных, полученные для каждого столбца. таким образом:

cols = ['c1', 'c2', 'c3']
x_new = pd.concat((x_ol[y_ol[c] == 1].assign(**{c: 0}) for c in cols)).sort_values('id')
y_new = pd.concat((y_ol[y_ol[c] == 1].assign(**{x: 1 if x == c else 0 for x in cols})
                   for c in cols)).sort_index()

Он дает как ожидалось

print(x_new)

   id  Date  c1  c2  c3
0   1  2000   0   0   1
0   1  2000   0   1   0
1   2  2001   0   0   1
1   2  2001   1   0   0
2   3  2002   0   1   0
2   3  2002   1   0   0
3   4  2003   0   1   1
3   4  2003   1   0   1
3   4  2003   1   1   0

и

print(y_new)

   c1  c2  c3
0   0   1   0
0   0   0   1
1   1   0   0
1   0   0   1
2   1   0   0
2   0   1   0
3   1   0   0
3   0   1   0
3   0   0   1
1 голос
/ 09 июля 2020

Чтобы создать новый y_ol, вы можете использовать stack to после замены 0 на where. Затем reset_index уровня 1, который фактически является именем столбца в y_ol с исходным 1.

df_ = y_ol.where(y_ol.eq(1)).stack().reset_index(level=1)
print (df_)
  level_1    0
0      c2  1.0
0      c3  1.0
1      c1  1.0
1      c3  1.0
2      c1  1.0
2      c2  1.0
3      c1  1.0
3      c2  1.0
3      c3  1.0

Используйте этот столбец с именем level_1 и numpy broadcasting, чтобы сравнить его с именами столбцов y_ol, чтобы получить True /Ложь. Измените тип на int и создайте новый фрейм данных y_ol по своему усмотрению.

y_ol_new = pd.DataFrame((df_['level_1'].to_numpy()[:, None] 
                         == y_ol.columns.to_numpy()).astype(int),
                        columns=y_ol.columns)
print (y_ol_new)
   c1  c2  c3
0   0   1   0
1   0   0   1
2   1   0   0
3   0   0   1
4   1   0   0
5   0   1   0
6   1   0   0
7   0   1   0
8   0   0   1

Теперь для X_ol вы можете reindex с индексом df_ для дублирования строк. Тогда вам просто нужно удалить y_ol_new.

X_ol_new = X_ol.reindex(df_.index).reset_index(drop=True)
X_ol_new[y_ol_new.columns] -= y_ol_new
print (X_ol_new)
   id  Date  c1  c2  c3
0   1  2000   0   0   1
1   1  2000   0   1   0
2   2  2001   0   0   1
3   2  2001   1   0   0
4   3  2002   0   1   0
5   3  2002   1   0   0
6   4  2003   0   1   1
7   4  2003   1   0   1
8   4  2003   1   1   0
...