1
votes

I have a dataframe:

     '1000'    '0100'    '0010'    '0001'    '1110'    '1101'    '1011'    '0111'
0        0         1         2         3         4         5         6         7
1       00        11        22        33        44        55        66        77

I would like to reverse the columns that their column names have their 1st and 2nd letters reversed and their 3rd and 4th as-is.

i.e.

1st col: 1000 → 2nd col: 0100

3rd col: 0010 → 5th col: 1110

4th col: 0001 → 6th col: 1101

7th col: 1011 → 8th col: 0111

I would like to have a dataframe like this:

     '0100'    '1000'    '1110'    '1101'    '0010'    '0001'    '1011'    '0111'
0        1         0         4         5         2         3         7         6
1       11        00        44        55        22        33        77        66

This is what I have for the reversion: reversed = ''.join('1' if x == '0' else '0' for x in 1stand2ndletter)

2

2 Answers

1
votes

I prefer using df.rename, much more "pythonic":

df = df.rename(columns = lambda x: x[1::-1]+x[2:])

If you want to flip 1st and 3rd, similarly:

df = df.rename(columns = lambda x: x[2]+x[1]+x[0]+x[3])
1
votes

Use your function in list comprehenion with add next 2 values and then change order of columns by original ordering in subset:

df.columns = df.columns.str.strip("'")
cols = df.columns

df.columns = [''.join('1' if x == '0' else '0' for x in y[:2])+y[2:] for y in df.columns]

df = df[cols]
print (df)
   1000  0100  0010  0001  1110  1101  1011  0111
0     1     0     4     5     2     3     7     6
1    11     0    44    55    22    33    77    66

EDIT: More general solution is convert values to 2d numpy array filled by boolean:

df.columns = df.columns.str.strip("'")
cols = df.columns

arr = np.array([[bool(int(y)) for y in x] for x in df.columns])
print (arr)
[[ True False False False]
 [False  True False False]
 [False False  True False]
 [False False False  True]
 [ True  True  True False]
 [ True  True False  True]
 [ True False  True  True]
 [False  True  True  True]]

And then for inverting use indexing, here : means all rows and columns positions form list and ~ invert mask:

pos = [0, 2]
arr[:, pos] = ~arr[:, pos]
print (arr)
[[False False  True False]
 [ True  True  True False]
 [ True False False False]
 [ True False  True  True]
 [False  True False False]
 [False  True  True  True]
 [False False False  True]
 [ True  True False  True]]

Last join back to list of strings:

df.columns = [''.join(str(int(y)) for y in x) for x in arr]
print (df)
   0010  1110  1000  1011  0100  0111  0001  1101
0     0     1     2     3     4     5     6     7
1     0    11    22    33    44    55    66    77

# df = df[cols]