简体   繁体   中英

merge every two columns on pandas.DataFrame

I'd like to pandas.DataFrame for every two columns.

For example, I have the following dataframe:

pd.DataFrame([[10,"5%", 20, "10%"],[30,"15%", 40,"20%"]], columns=['error1', '(%)', 'error2', '(%)'])

在此输入图像描述

Then, what I'd like to get is the following dataframe:

pd.DataFrame([["10 (5%)", "20 (10%)"],["30 (15%)", "40 (20%)"]], columns=['error1 (%)', 'error2 (%)'])

在此输入图像描述

For this data frame:

print(df)

   error1  (%)  error2  (%)
0      10   5%      20  10%
1      30  15%      40  20%

This works:

def make_func(offset=0):
    def func(x):
        return '{} ({})'.format(x[0 + offset], x[1 + offset])
    return func


df2 = pd.DataFrame()
for offset in range(0, df.shape[1], 2):
    df2['{} (%)'.format(df.columns[offset])] = df.apply(make_func(offset), axis=1)

Result:

print(df2)

  error1 (%) error2 (%)
0    10 (5%)   20 (10%)
1   30 (15%)   40 (20%)

You can try:

import pandas as pd

df = pd.DataFrame([[10,"5%", 20, "10%"],[30,"15%", 40,"20%"]], 
                  columns=['error1', '(%)', 'error2', '(%)'])
print df
   error1  (%)  error2  (%)
0      10   5%      20  10%
1      30  15%      40  20%

cols = (' '.join(w) for w in zip(df.columns[::2], df.columns[1::2]))

print pd.DataFrame(df.ix[:, ::2].astype(str).values + 
                                               ' (' + 
                              df.ix[:, 1::2].values +
                                                 ')', index=df.index, columns=cols)

  error1 (%) error2 (%)
0    10 (5%)   20 (10%)
1   30 (15%)   40 (20%)                                                     

Odd and even columns names:

In [80]: df.columns[::2]
Out[80]: Index([u'error1', u'error2'], dtype='object')

In [81]: df.columns[1::2]
Out[81]: Index([u'(%)', u'(%)'], dtype='object')

List of tuples by zip :

In [82]: zip(df.columns[::2], df.columns[1::2])
Out[82]: [('error1', '(%)'), ('error2', '(%)')]

Generator - join items of tuples:

In [83]: (' '.join(w) for w in zip(df.columns[::2], df.columns[1::2]))
Out[83]: <generator object <genexpr> at 0x0000000015158EE8>

In [84]: list((' '.join(w) for w in zip(df.columns[::2], df.columns[1::2])))
Out[84]: ['error1 (%)', 'error2 (%)']    

Cast integer values to string by astype and convert to numpy array by df.values :

In [89]: df.ix[:, ::2].astype(str).values
Out[89]: 
array([['10', '20'],
       ['30', '40']], dtype=object)

In [90]: df.ix[:, 1::2].values
Out[90]: 
array([['5%', '10%'],
       ['15%', '20%']], dtype=object)

Comparing with another answer [2 rows x 4000 columns] :

df = pd.DataFrame([[10,"5%", 20, "10%"]*1000,[30,"15%", 40,"20%"]*1000], 
                  columns=['error1', '(%)', 'error2', '(%)']*1000)

def VAL(df):
    cols = (' '.join(w) for w in zip(df.columns[::2], df.columns[1::2]))

    return pd.DataFrame(df.ix[:, ::2].astype(str).values + 
                                                   ' (' + 
                              df.ix[:, 1::2].values +
                                                 ')', index=df.index, columns=cols)
def APL(df):
    def make_func(offset=0):
        def func(x):
            return '{} ({})'.format(x[0 + offset], x[1 + offset])
        return func

    df2 = pd.DataFrame()
    for offset in range(0, df.shape[1], 2):
        df2['{} (%)'.format(df.columns[offset])] = df.apply(make_func(offset), axis=1)
    return df2

VAL(df)  
APL(df)     
In [97]: %timeit VAL(df)
    ...: %timeit APL(df)
    ...: 
100 loops, best of 3: 10.4 ms per loop
1 loops, best of 3: 3.65 s per loop                                          

This is not the fastest solution, but it is probably the most readable one:

import pandas as pd


# define how you want to transform each list into a list of coupled data
def make_couples(ls):
    return ['{} ({})'.format(*item) for item in zip(ls[::2], ls[1::2])]

df = pd.DataFrame([[10,"5%", 20, "10%"],[30,"15%", 40,"20%"]], columns=['error1', '%', 'error2', '%'])
df2 = pd.DataFrame(columns=make_couples(df.columns), data=map(make_couples, df.values))

df2 will be:

  error1 (%) error2 (%)
0    10 (5%)   20 (10%)
1   30 (15%)   40 (20%)

Readability counts =).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM