【问题标题】:Convert values in column from hex to binary in pandas data frame在熊猫数据框中将列中的值从十六进制转换为二进制
【发布时间】:2019-04-14 15:32:27
【问题描述】:

我在 pandas 数据框中有一列带有十六进制值,例如:

Data
1A
2B
BB
FF
A7
78
CB

我想将十六进制值转换为二进制,然后从二进制取前 3 位,最后将 3 位值转换为十进制。

二进制数据列将是:

Data
00011010
00101011
10111011
11111111
10100111
01111000
11001011

前 3 位:

Data
010
011
011
111
111
000
011

最后是所需的十进制值:

Data
2
3
3
7
7
0
3

如何做到这一点?我尝试使用 bin() 函数,但它不适用于 pandas 数据帧。

【问题讨论】:

  • 您能否分享您的工作,以便我们轻松复制。
  • 我分享了我能分享的一切......我希望我能分享更多,但这是不允许的。

标签: python pandas dataframe binary hex


【解决方案1】:

我们可以通过一系列动作来做到这一点:

  1. 首先我们将十六进制数转换为int.apply(int, base=16)
  2. 接下来我们将其转换为二进制数据,使用.apply(bin)
  3. 接下来我们用.str[2:]分割前两个字符;
  4. 然后我们用.str[-3:]获得最后三个字符;和
  5. 最后我们再次将这些解释为ints,.apply(int, base=2)

所以:

>>> df.Data.apply(int, base=16).apply(bin).str[2:].str[-3:].apply(int, base=2)
0    2
1    3
2    3
3    7
4    7
5    0
6    3
Name: Data, dtype: int64

然而,我们可以在这里使用另一种策略:

  1. 我们首先将十六进制数转换为int;和
  2. 然后我们按位和0b111 应用。

例如:

>>> df.Data.apply(int, base=16) & 0b111
0    2
1    3
2    3
3    7
4    7
5    0
6    3
Name: Data, dtype: int64

第二次尝试不仅更简单,而且速度也更快,大约提高了 66%:

>>> timeit(first_strategy, number=10000)
6.962630775000434
>>> timeit(second_strategy, number=10000)
2.330652763019316

对于重复样本数据 100 次的数据框,我们得到:

>>> timeit(first_strategy, number=10000)
17.603060900000855
>>> timeit(second_strategy, number=10000)
5.901462858979357

这又快了 66%。

【讨论】:

  • 我喜欢另一种策略...我可能会想使用0b111 而不是7(或者可能是(1 << N) - 1,如果它将是“最后一个N 位”,其中N 不仅仅是一对 ) 之类的东西,而是......
  • 非常感谢。它可以工作...但是如果我必须从一个字节中的第 2 到第 5 个位置提取 3 位(例如,从 "10010110" 它是 "010") ,我该怎么办?对于第一个解决方案,我可以放入 str[p1:p2] 并使用 None 如果它是字符串的结尾。但是对于第二种解决方案,顺便说一句,我非常喜欢,如何提取我想要的位?
  • @slobokv83:你可以先除以(1<<2)(所以4),比如(df.Data.apply(int, base=16) // (1 << 2)) & 0b111
  • 好的,我知道了。谢谢你。我必须转移到我想要获取位的位置......并且我必须在第一个解决方案中添加它,我修改它以便使用前导零,然后可以从我想要的位置提取。比如:df.Data.apply(int, base=16).apply(bin).str[2:].str.zfill(width).str[-p1:p2].apply(int, base=2)
  • @slobokv83: 说得好,可以用(df.Data.apply(int, base=16) // (1 << o)) & ((1 << w) - 1)获取oo+w位之间的值,不需要切片,zfill`等。
【解决方案2】:

你可以使用:

df.Data.apply(lambda v: int(format(int(v, 16), '08b')[-3:], 2))

这给了你:

0    2
1    3
2    3
3    7
4    7
5    0
6    3
Name: Data, dtype: int64

这些步骤是:

  • 获取原始数据并使用 int(number, 16) 将其转换为十进制(基数 16 是十六进制)(int('1A', 16) == 26)
  • 获取该数字并将其格式化为二进制字符串format(number, '08b') 为您提供左侧填充的 0/1 的零字符串 (format(26, '08b') == '00011010')
  • 取该字符串的最后 3 个字符 [-3:] ('010') 并将其转换为以 2 为底的十进制,int(binary_string[-3:], 2) 为您提供:2

【讨论】:

  • 非常感谢。它工作正常......我还有一个问题 - 如果我需要位数组的长度是可变的,我必须做什么?你放了'08b',如果我想在某个时刻变成'16b',我应该放像'{length}b'并为长度提供一些价值?
猜你喜欢
  • 2022-01-06
  • 2016-06-05
  • 2011-08-27
  • 2012-06-26
  • 1970-01-01
  • 2012-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多