На це питання вже дано відповіді, але я вважаю, що було б непогано вкласти в суміш деякі корисні методи, які раніше не обговорювались, і порівняти всі запропоновані на сьогодні методи з точки зору ефективності.
Ось декілька корисних рішень цієї проблеми в порядку збільшення продуктивності.
Це простий str.format
підхід.
df['baz'] = df.agg('{0[bar]} is {0[foo]}'.format, axis=1)
df
foo bar baz
0 a 1 1 is a
1 b 2 2 is b
2 c 3 3 is c
Ви також можете використовувати форматування f-рядка тут:
df['baz'] = df.agg(lambda x: f"{x['bar']} is {x['foo']}", axis=1)
df
foo bar baz
0 a 1 1 is a
1 b 2 2 is b
2 c 3 3 is c
Перетворіть стовпці для об’єднання як chararrays
, а потім складіть їх разом.
a = np.char.array(df['bar'].values)
b = np.char.array(df['foo'].values)
df['baz'] = (a + b' is ' + b).astype(str)
df
foo bar baz
0 a 1 1 is a
1 b 2 2 is b
2 c 3 3 is c
Я не можу перебільшити, наскільки недооцінене розуміння списку є в пандах.
df['baz'] = [str(x) + ' is ' + y for x, y in zip(df['bar'], df['foo'])]
Крім того, використання str.join
concat (також буде краще масштабуватися):
df['baz'] = [
' '.join([str(x), 'is', y]) for x, y in zip(df['bar'], df['foo'])]
df
foo bar baz
0 a 1 1 is a
1 b 2 2 is b
2 c 3 3 is c
Розуміння списків перевершує маніпулювання рядками, оскільки рядкові операції за своєю суттю важко векторизувати, а більшість "векторизованих" функцій панд в основному є обгортками навколо циклів. Я багато писав про цю тему в розділі « Для циклів з пандами» - коли мені потрібно дбати? . Загалом, якщо вам не доводиться турбуватися про вирівнювання індексу, використовуйте розуміння списку, маючи справу з операціями рядка та регулярного виразу.
Наведений вище список за замовчуванням не обробляє NaN. Однак ви завжди можете написати функцію, яка обгортає спробу, за винятком випадків, коли вам потрібно було її обробити.
def try_concat(x, y):
try:
return str(x) + ' is ' + y
except (ValueError, TypeError):
return np.nan
df['baz'] = [try_concat(x, y) for x, y in zip(df['bar'], df['foo'])]
perfplot
Вимірювання продуктивності
Графік, сформований за допомогою perfplot . Ось повний перелік кодів .
Функції
def brenbarn(df):
return df.assign(baz=df.bar.map(str) + " is " + df.foo)
def danielvelkov(df):
return df.assign(baz=df.apply(
lambda x:'%s is %s' % (x['bar'],x['foo']),axis=1))
def chrimuelle(df):
return df.assign(
baz=df['bar'].astype(str).str.cat(df['foo'].values, sep=' is '))
def vladimiryashin(df):
return df.assign(baz=df.astype(str).apply(lambda x: ' is '.join(x), axis=1))
def erickfis(df):
return df.assign(
baz=df.apply(lambda x: f"{x['bar']} is {x['foo']}", axis=1))
def cs1_format(df):
return df.assign(baz=df.agg('{0[bar]} is {0[foo]}'.format, axis=1))
def cs1_fstrings(df):
return df.assign(baz=df.agg(lambda x: f"{x['bar']} is {x['foo']}", axis=1))
def cs2(df):
a = np.char.array(df['bar'].values)
b = np.char.array(df['foo'].values)
return df.assign(baz=(a + b' is ' + b).astype(str))
def cs3(df):
return df.assign(
baz=[str(x) + ' is ' + y for x, y in zip(df['bar'], df['foo'])])