Доступ, str
який доступний для pandas.Series
об'єктів dtype == object
, насправді є ітерабельним.
Припустимо pandas.DataFrame
df
:
df = pd.DataFrame(dict(col=[*zip('abcdefghij', range(10, 101, 10))]))
df
col
0 (a, 10)
1 (b, 20)
2 (c, 30)
3 (d, 40)
4 (e, 50)
5 (f, 60)
6 (g, 70)
7 (h, 80)
8 (i, 90)
9 (j, 100)
Ми можемо перевірити, чи це ітерація
from collections import Iterable
isinstance(df.col.str, Iterable)
True
Потім ми можемо призначити з нього, як і інші ітерабелі:
var0, var1 = 'xy'
print(var0, var1)
x y
Найпростіше рішення
Отже, в одному рядку ми можемо призначити обидва стовпці
df['a'], df['b'] = df.col.str
df
col a b
0 (a, 10) a 10
1 (b, 20) b 20
2 (c, 30) c 30
3 (d, 40) d 40
4 (e, 50) e 50
5 (f, 60) f 60
6 (g, 70) g 70
7 (h, 80) h 80
8 (i, 90) i 90
9 (j, 100) j 100
Швидше рішення
Тільки дещо складніше, ми можемо використати zip
для створення подібного ітератора
df['c'], df['d'] = zip(*df.col)
df
col a b c d
0 (a, 10) a 10 a 10
1 (b, 20) b 20 b 20
2 (c, 30) c 30 c 30
3 (d, 40) d 40 d 40
4 (e, 50) e 50 e 50
5 (f, 60) f 60 f 60
6 (g, 70) g 70 g 70
7 (h, 80) h 80 h 80
8 (i, 90) i 90 i 90
9 (j, 100) j 100 j 100
В лінію
Значення, не мутувати існуючі df
Це працює, оскільки assign
приймає аргументи ключових слів, де ключові слова - це нові (або існуючі) назви стовпців, а значення будуть значеннями нового стовпця. Ви можете скористатися словником і розпакувати його, **
і він буде виконувати роль аргументів ключового слова. Отже, це розумний спосіб присвоєння нового стовпця з іменем, 'g'
який є першим елементом у df.col.str
ітерабелі, а 'h'
це другим елементом у df.col.str
ітерабелі.
df.assign(**dict(zip('gh', df.col.str)))
col g h
0 (a, 10) a 10
1 (b, 20) b 20
2 (c, 30) c 30
3 (d, 40) d 40
4 (e, 50) e 50
5 (f, 60) f 60
6 (g, 70) g 70
7 (h, 80) h 80
8 (i, 90) i 90
9 (j, 100) j 100
Моя версія list
підходу
З сучасним розумінням списку та розпаковуванням змінних.
Примітка: також вбудований за допомогоюjoin
df.join(pd.DataFrame([*df.col], df.index, [*'ef']))
col g h
0 (a, 10) a 10
1 (b, 20) b 20
2 (c, 30) c 30
3 (d, 40) d 40
4 (e, 50) e 50
5 (f, 60) f 60
6 (g, 70) g 70
7 (h, 80) h 80
8 (i, 90) i 90
9 (j, 100) j 100
Мутуюча версія буде
df[['e', 'f']] = pd.DataFrame([*df.col], df.index)
Тест наївного часу
Короткий кадр даних
Використовуйте визначену вище
%timeit df.assign(**dict(zip('gh', df.col.str)))
%timeit df.assign(**dict(zip('gh', zip(*df.col))))
%timeit df.join(pd.DataFrame([*df.col], df.index, [*'gh']))
1.16 ms ± 21.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
635 µs ± 18.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
795 µs ± 42.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Довгий фрейм даних
В 10 ^ 3 рази більше
df = pd.concat([df] * 1000, ignore_index=True)
%timeit df.assign(**dict(zip('gh', df.col.str)))
%timeit df.assign(**dict(zip('gh', zip(*df.col))))
%timeit df.join(pd.DataFrame([*df.col], df.index, [*'gh']))
11.4 ms ± 1.53 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.1 ms ± 41.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.33 ms ± 35.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)