johnnyb johnnyb - 9 months ago 49
Python Question

Convert multitype series containing rows of hex to ascii

I have a Dataframe like below:

type value
hex "6d,79,20,6e,61,6d,65,20,69,73,20,6a,6f,68,6e,0a"
name john
dynamic 12
action encroach
hex_2 "4d,69,6e,65,20,69,73,20,73,61,75,6c,2c,20,6e,69,63,65,20,74,6f,20,6d,65,65,74,20,79,6f,75,2e,20"
hex "4d,79,20,6e,61,6d,65,20,69,73,20,4d,61,74,74"
name Matt
dynamic 91
action penalty
hex_2 "49,20,61,6d,20,61,6e,20,65,6e,63,6f,64,65,64,20,6d,65,73,73,61,67,65,20,74,68,61,74,20,49,20,68,61,76,65,20,74,6f,20,6b,65,65,70,20,69,6e,74,65,72,6e,61,6c,20,74,6f,20,6d,79,20,6f,72,67,61,6e,69,7a,61,74,69,6f,6e,2e,20"


How can I conditionally reformat the hex and hex_2 to ascii?

Current code is as follows to convert hex to ascii with function call:

def ascii_convert(char):
value = int(char, 16)
if 32 <= value < 128:
return chr(value)
else:
return char

Current Failed attempt at converting:
print(df[df['type'].str.contains('hex|hex_2').apply(lambda x: ascii_convert(x)))


Expected Output:

type value
hex my name is john # converted
name john # Untouched
dynamic 12 # Untouched
action encroach # Untouched
hex_2 Mine is saul, nice to meet you. # converted
hex My name is Matt # converted
name Matt # Untouched
dynamic 91 # Untouched
action penalty # Untouched
hex_2 I am an encoded message that I have to keep internal to my organization. # converted


I know the conversion function works for the characters but am having trouble using the function within my specific criteria. My data type labels can have 5 or six different labels I would like to convert from hex to ascii such as the hex and hex_2.

Any help would be amazing. thank you.

Answer Source

The attempt is failing because with str.contains('hex|hex_2') you're trying to match the exact string 'hex|hex_2'. but no columns exist with that name.

Instead, since you confirmed that all the columns you want to convert have the string 'hex' in the name this should do.

 data["value"] = df.apply(lambda x: convert_ascii(x["value"]) \
 if 'hex' in x["type"] else x["value"], axis=1)

This selects the values of rows with 'hex' in type column and converts them, leaving the others columns untouched

here is an example:

  one  two labels
0  70  1      o
1  67  0      b
2  57  1      o
3  64  1      b
4  74  0      o
5  65  1      b
6  56  1      o
7  59  1      b
8  60  1      o
9  63  0      b

apply function and update the labels column:

data["type"] = data.apply(lambda x: x["labels"] *4 \
               if x["one"] >= 60 else x["labels"], axis=1)

   one  two labels
0   70    1   oooo
1   67    0   bbbb
2   57    1      o
3   64    1   bbbb
4   74    0   oooo
5   65    1   bbbb
6   56    1      o
7   59    1      b
8   60    1   oooo
9   63    0   bbbb