применить против вложенных для циклов - PullRequest
0 голосов
/ 03 сентября 2018

Я пытаюсь построить в Python фрейм данных, заполненный 1 и 0, в зависимости от числа в одном столбце:

Date        Hour
2005-01-01  1
2005-01-01  2
2005-01-01  3
2005-01-01  4

Я хочу создать новые столбцы на основе числа в «Часе» и заполнить каждый столбец 1, если эта строка равна значению в «Часе», или 0, если нет.

Date        Hour HE1 HE2 HE3 HE4
2005-01-01  1    1   0   0   0
2005-01-01  2    0   1   0   0
2005-01-01  3    0   0   1   0
2005-01-01  4    0   0   0   1

Я могу сделать это с помощью этого кода, но это занимает много времени:

for x in range(1,5):
    _HE = 'HE' + str(x)
    for i in load.index:
        load.at[i, _HE] = 1 if load.at[i,'Hour']==x else 0

Мне кажется, что это отличное приложение (без каламбура) для .apply (), но я не могу заставить его работать правильно.

Как бы вы ускорили это?

Ответы [ 3 ]

0 голосов
/ 03 сентября 2018

Даже если это действительно похоже на ответ @ jezrael, но это также намного лучше (он просто использует .str accessor для get_dummies:

print(df.join(df['Hour'].astype(str).str.get_dummies().add_prefix('HE')))

Выход:

         Date  Hour  HE1  HE2  HE3  HE4
0  2005-01-01     1    1    0    0    0
1  2005-01-01     2    0    1    0    0
2  2005-01-01     3    0    0    1    0
3  2005-01-01     4    0    0    0    1
0 голосов
/ 03 сентября 2018

pandas.factorize и назначение среза массива

j, h = pd.factorize(df.Hour)
i = np.arange(len(df))

b = np.zeros((len(df), len(h)), dtype=h.dtype)
b[i, j] = 1

df.join(pd.DataFrame(b, df.index, h).add_prefix('HE'))

         Date  Hour  HE1  HE2  HE3  HE4
0  2005-01-01     1    1    0    0    0
1  2005-01-01     2    0    1    0    0
2  2005-01-01     3    0    0    1    0
3  2005-01-01     4    0    0    0    1
0 голосов
/ 03 сентября 2018

В pandas петли не рекомендуются, потому что медленнее, если существует какое-либо векторизованное решение.

Примечание: в функции apply также есть петли под капотом.

Так что используйте pandas.get_dummies и DataFrame.add_prefix и join для добавления к оригиналу df:

df = df.join(pd.get_dummies(df['Hour'].astype(str)).add_prefix('HE'))
print (df)
         Date  Hour  HE1  HE2  HE3  HE4
0  2005-01-01     1    1    0    0    0
1  2005-01-01     2    0    1    0    0
2  2005-01-01     3    0    0    1    0
3  2005-01-01     4    0    0    0    1

Аналогичные функции имеют разную производительность:

df = pd.concat([df] * 1000, ignore_index=True)

In [62]: %timeit df.join(pd.get_dummies(df['Hour'].astype(str)).add_prefix('HE'))
3.54 ms ± 277 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

#U9-Forward solution
In [63]: %timeit df.join(df['Hour'].astype(str).str.get_dummies().add_prefix('HE'))
61.6 ms ± 297 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
...