source

Pandas 데이터 프레임에서 여러 열 값을 하나의 열로 연결하는 방법

lovecheck 2023. 10. 4. 22:02
반응형

Pandas 데이터 프레임에서 여러 열 값을 하나의 열로 연결하는 방법

이 질문은 앞에 올린 것과 같습니다.두 개의 열을 연결하는 대신 세 개의 열을 연결합니다.

다음은 두 개의 열을 결합한 것입니다.

df = DataFrame({'foo':['a','b','c'], 'bar':[1, 2, 3], 'new':['apple', 'banana', 'pear']})

df['combined']=df.apply(lambda x:'%s_%s' % (x['foo'],x['bar']),axis=1)

df
    bar foo new combined
0   1   a   apple   a_1
1   2   b   banana  b_2
2   3   c   pear    c_3

이 명령어로 세 개의 열을 결합하고 싶은데 작동이 안 돼요. 무슨 방법이 없을까요?

df['combined']=df.apply(lambda x:'%s_%s' % (x['bar'],x['foo'],x['new']),axis=1)

를 이용한 다른 솔루션DataFrame.apply(), 더 많은 열에 참여하고자 할 때 타이핑이 약간 줄어들고 확장성이 향상됩니다.

cols = ['foo', 'bar', 'new']
df['combined'] = df[cols].apply(lambda row: '_'.join(row.values.astype(str)), axis=1)

문자열 연결을 사용하여 구분 기호가 있든 없든 열을 결합할 수 있습니다.문자열이 아닌 열에서 형식을 변환해야 합니다.

In[17]: df['combined'] = df['bar'].astype(str) + '_' + df['foo'] + '_' + df['new']

In[17]:df
Out[18]: 
   bar foo     new    combined
0    1   a   apple   1_a_apple
1    2   b  banana  2_b_banana
2    3   c    pear    3_c_pear

시리즈 방법을 사용하여 조합하려는 열이 더 많은 경우str.cat편리할 수도 있습니다.

df["combined"] = df["foo"].str.cat(df[["bar", "new"]].astype(str), sep="_")

기본적으로 첫 번째 열(아직 유형이 아닌 경우)을 선택합니다.str, 당신은 추가해야 합니다..astype(str)다른 열(선택적 구분 문자로 구분)을 추가할 수 있습니다.

두 솔루션(30K 행 DF의 경우)에 대해 시간을 비교하고자 했을 뿐입니다.

In [1]: df = DataFrame({'foo':['a','b','c'], 'bar':[1, 2, 3], 'new':['apple', 'banana', 'pear']})

In [2]: big = pd.concat([df] * 10**4, ignore_index=True)

In [3]: big.shape
Out[3]: (30000, 3)

In [4]: %timeit big.apply(lambda x:'%s_%s_%s' % (x['bar'],x['foo'],x['new']),axis=1)
1 loop, best of 3: 881 ms per loop

In [5]: %timeit big['bar'].astype(str)+'_'+big['foo']+'_'+big['new']
10 loops, best of 3: 44.2 ms per loop

몇 가지 추가 옵션:

In [6]: %timeit big.ix[:, :-1].astype(str).add('_').sum(axis=1).str.cat(big.new)
10 loops, best of 3: 72.2 ms per loop

In [11]: %timeit big.astype(str).add('_').sum(axis=1).str[:-1]
10 loops, best of 3: 82.3 ms per loop

아마도 가장 빠른 솔루션은 일반 Python에서 작동하는 것입니다.

Series(
    map(
        '_'.join,
        df.values.tolist()
        # when non-string columns are present:
        # df.values.astype(str).tolist()
    ),
    index=df.index
)

@MaxU 답변과 비교(사용)big숫자 열과 문자열 열이 모두 있는 데이터 프레임:

%timeit big['bar'].astype(str) + '_' + big['foo'] + '_' + big['new']
# 29.4 ms ± 1.08 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)


%timeit Series(map('_'.join, big.values.astype(str).tolist()), index=big.index)
# 27.4 ms ± 2.36 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

@derchambers 답변과 비교(사용)df데이터 프레임(모든 열이 문자열인 경우):

from functools import reduce

def reduce_join(df, columns):
    slist = [df[x] for x in columns]
    return reduce(lambda x, y: x + '_' + y, slist[1:], slist[0])

def list_map(df, columns):
    return Series(
        map(
            '_'.join,
            df[columns].values.tolist()
        ),
        index=df.index
    )

%timeit df1 = reduce_join(df, list('1234'))
# 602 ms ± 39 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit df2 = list_map(df, list('1234'))
# 351 ms ± 12.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

@allen이 제시한 답변은 비교적 일반적이지만 더 큰 데이터 프레임에 대해서는 성능이 부족할 수 있습니다.

축소를 통해 훨씬 더 나은 효과를 얻을 수 있습니다.

from functools import reduce

import pandas as pd

# make data
df = pd.DataFrame(index=range(1_000_000))
df['1'] = 'CO'
df['2'] = 'BOB'
df['3'] = '01'
df['4'] = 'BILL'


def reduce_join(df, columns):
    assert len(columns) > 1
    slist = [df[x].astype(str) for x in columns]
    return reduce(lambda x, y: x + '_' + y, slist[1:], slist[0])


def apply_join(df, columns):
    assert len(columns) > 1
    return df[columns].apply(lambda row:'_'.join(row.values.astype(str)), axis=1)

# ensure outputs are equal
df1 = reduce_join(df, list('1234'))
df2 = apply_join(df, list('1234'))
assert df1.equals(df2)

# profile
%timeit df1 = reduce_join(df, list('1234'))  # 733 ms
%timeit df2 = apply_join(df, list('1234'))   # 8.84 s

%s이(가) 누락된 것 같습니다.

df['combined']=df.apply(lambda x:'%s_%s_%s' % (x['bar'],x['foo'],x['new']),axis=1)

먼저 열을 str로 변환합니다.그런 다음 .T.agg('_'.join) 함수를 사용하여 연결합니다.자세한 정보는 여기에서 확인할 수 있습니다.

# Initialize columns
cols_concat = ['first_name', 'second_name']

# Convert them to type str
df[cols_concat] = df[cols_concat].astype('str')

# Then concatenate them as follows
df['new_col'] = df[cols_concat].T.agg('_'.join)
df = DataFrame({'foo':['a','b','c'], 'bar':[1, 2, 3], 'new':['apple', 'banana', 'pear']})

df['combined'] = df['foo'].astype(str)+'_'+df['bar'].astype(str)

문자열('_')로 연결하는 경우 열을 원하는 문자열로 변환하고 데이터 프레임을 연결할 수 있습니다.

df['New_column_name'] = df['Column1'].map(str) + 'X' + df['Steps']

X= x는 병합된 두 열을 구분할 구분 기호(예: 공백)입니다.

연결할 열 목록이 있고 구분자를 사용하고 싶은 경우 다음과 같이 수행할 수 있습니다.

def concat_columns(df, cols_to_concat, new_col_name, sep=" "):
    df[new_col_name] = df[cols_to_concat[0]]
    for col in cols_to_concat[1:]:
        df[new_col_name] = df[new_col_name].astype(str) + sep + df[col].astype(str)

이것은 보다 빠를 것입니다.apply연결할 임의 수의 열을 사용합니다.

@derchamber 한가지 해결책을 더 찾았습니다.

import pandas as pd

# make data
df = pd.DataFrame(index=range(1_000_000))
df['1'] = 'CO'
df['2'] = 'BOB'
df['3'] = '01'
df['4'] = 'BILL'

def eval_join(df, columns):

    sum_elements = [f"df['{col}']" for col in columns]
    to_eval = "+ '_' + ".join(sum_elements)

    return eval(to_eval)


#profile
%timeit df3 = eval_join(df, list('1234')) # 504 ms

구현을 보다 효율적으로 수행할 수 있는 기능을 만들 수 있습니다(특히 구현 중에 이 기능을 여러 번 사용하는 경우).

def concat_cols(df, cols_to_concat, new_col_name, separator):  
    df[new_col_name] = ''
    for i, col in enumerate(cols_to_concat):
        df[new_col_name] += ('' if i == 0 else separator) + df[col].astype(str)
    return df

샘플 사용량:

test = pd.DataFrame(data=[[1,2,3], [4,5,6], [7,8,9]], columns=['a', 'b', 'c'])
test = concat_cols(test, ['a', 'b', 'c'], 'concat_col', '_')

@로Allen 응답에 따름
을 다른 assign:

df.assign(
    combined = lambda x: x[cols].apply(
        lambda row: "_".join(row.values.astype(str)), axis=1
  )
)

의 열을 가 3 하면, 는 3 이고,'%s_%s_%s'만 아니라, '%s_%s'이 그 을 할 입니다. 다음이 그 일을 할 것입니다.

df['combined'] = df.apply(lambda x: '%s_%s_%s' % (x['foo'], x['bar'], x['new']), axis=1)

[Out]:
  foo  bar     new    combined
0   a    1   apple   a_1_apple
1   b    2  banana  b_2_banana
2   c    3    pear    c_3_pear

또는 결합하려는 열을 저장하기 위해 별도의 목록을 작성하려는 경우 다음과 같은 작업을 수행합니다.

columns = ['foo', 'bar', 'new']

df['combined'] = df.apply(lambda x: '_'.join([str(x[i]) for i in columns]), axis=1)

[Out]:
  foo  bar     new    combined
0   a    1   apple   a_1_apple
1   b    2  banana  b_2_banana
2   c    3    pear    c_3_pear

이 마지막 항목은 목록에서 열 이름을 간단히 변경하거나 추가할 수 있기 때문에 더 편리합니다. 변경할 필요가 적을 것입니다.

언급URL : https://stackoverflow.com/questions/39291499/how-to-concatenate-multiple-column-values-into-a-single-column-in-pandas-datafra

반응형