다음이 있습니다 DataFrame
.
from pandas import *
df = DataFrame({'foo':['a','b','c'], 'bar':[1, 2, 3]})
다음과 같이 보입니다.
bar foo
0 1 a
1 2 b
2 3 c
이제 다음과 같은 것을 갖고 싶습니다.
bar
0 1 is a
1 2 is b
2 3 is c
이것을 어떻게 달성 할 수 있습니까? 다음을 시도했습니다.
df['foo'] = '%s is %s' % (df['bar'], df['foo'])
그러나 그것은 나에게 잘못된 결과를 제공합니다.
>>>print df.ix[0]
bar a
foo 0 a
1 b
2 c
Name: bar is 0 1
1 2
2
Name: 0
멍청한 질문에 대해 미안하지만이 팬더 : DataFrame에서 두 개의 열을 결합하는 것은 나에게 도움이되지 않았습니다.
답변
df['bar'] = df.bar.map(str) + " is " + df.foo
.
답변
이 질문은 이미 답변되었지만 이전에 논의되지 않은 유용한 방법을 혼합하여 지금까지 제안한 모든 방법을 성능 측면에서 비교하는 것이 좋을 것이라고 생각합니다.
성능 순서를 높이기 위해이 문제에 대한 몇 가지 유용한 솔루션이 있습니다.
DataFrame.agg
이것은 간단한 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
char.array
기반 연결
열을로 연결하도록 변환 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
목록 이해 와zip
팬더에서 목록 이해력이 얼마나 과소 평가되었는지 과소 평가할 수 없습니다.
df['baz'] = [str(x) + ' is ' + y for x, y in zip(df['bar'], df['foo'])]
또는을 사용 str.join
하여 연결합니다 (확장도 향상됨).
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
문자열 연산은 본질적으로 벡터화하기 어렵고 대부분의 pandas “벡터화 된”함수는 기본적으로 루프를 둘러싼 래퍼이기 때문에 목록 이해는 문자열 조작에 탁월합니다. 판다를 사용한 For 루프 에서이 주제에 대해 광범위하게 작성했습니다. 언제 관심을 가져야합니까? . 일반적으로 인덱스 정렬에 대해 걱정할 필요가 없으면 문자열 및 정규식 작업을 처리 할 때 목록 이해를 사용하십시오.
위의 목록 구성은 기본적으로 NaN을 처리하지 않습니다. 그러나 처리해야하는 경우 항상 try-except를 래핑하는 함수를 작성할 수 있습니다.
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'])])
답변
코드의 문제는 모든 행에 작업을 적용하려는 것입니다. 하지만 작성한 방식은 전체 ‘bar’및 ‘foo’열을 가져 와서 문자열로 변환하고 하나의 큰 문자열을 반환합니다. 다음과 같이 작성할 수 있습니다.
df.apply(lambda x:'%s is %s' % (x['bar'],x['foo']),axis=1)
다른 답변보다 길지만 더 일반적입니다 (문자열이 아닌 값과 함께 사용할 수 있음).
답변
당신은 또한 사용할 수 있습니다
df['bar'] = df['bar'].str.cat(df['foo'].values.astype(str), sep=' is ')
답변
df.astype(str).apply(lambda x: ' is '.join(x), axis=1)
0 1 is a
1 2 is b
2 3 is c
dtype: object
답변
@DanielVelkov 대답은 적절한 대답이지만 문자열 리터럴을 사용하는 것이 더 빠릅니다.
# Daniel's
%timeit df.apply(lambda x:'%s is %s' % (x['bar'],x['foo']),axis=1)
## 963 µs ± 157 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
# String literals - python 3
%timeit df.apply(lambda x: f"{x['bar']} is {x['foo']}", axis=1)
## 849 µs ± 4.28 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
답변
series.str.cat
이 문제에 접근하는 가장 유연한 방법입니다.
에 대한 df = pd.DataFrame({'foo':['a','b','c'], 'bar':[1, 2, 3]})
df.foo.str.cat(df.bar.astype(str), sep=' is ')
>>> 0 a is 1
1 b is 2
2 c is 3
Name: foo, dtype: object
또는
df.bar.astype(str).str.cat(df.foo, sep=' is ')
>>> 0 1 is a
1 2 is b
2 3 is c
Name: bar, dtype: object
가장 중요한 것은 (와 달리 .join()
) Null
값 을 무시하거나 na_rep
매개 변수로 바꿀 수 있다는 것 입니다.