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)
Наивный тест времени
Короткий DataFrame
Используйте один, определенный выше
%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)