根据位数拆分pandas数据帧列

时间:2022-03-26 02:42:39

I have a pandas dataframe which has two columns key and value, and the value always consists of a 8 digit number something like

我有一个pandas数据帧,它有两列key和value,值总是由8位数字组成

>df1
key value
10  10000100
20  10000000
30  10100000
40  11110000

Now I need to take the value column and split it on the digits present, such that my result is a new data frame

现在我需要取值列并将其拆分为存在的数字,这样我的结果就是一个新的数据帧

>df_res
key 0 1 2 3 4 5 6 7
10  1 0 0 0 0 1 0 0
20  1 0 0 0 0 0 0 0
30  1 0 1 0 0 0 0 0
40  1 1 1 1 0 0 0 0

I cannot change the input data format, the most conventional thing I thought was to convert the value to a string and loop through each digit char and put it in a list, however am looking for something more elegant and faster, kindly help.

我无法改变输入数据格式,我认为最传统的事情是将值转换为字符串并循环遍历每个数字字符并将其放入列表中,但是我正在寻找更优雅,更快速的东西,请帮忙。

EDIT: The input is not in string, it is integer.

编辑:输入不在字符串中,它是整数。

4 个解决方案

#1


3  

One approach could be -

一种方法可能是 -

arr = df.value.values.astype('S8')
df = pd.DataFrame(np.fromstring(arr, dtype=np.uint8).reshape(-1,8)-48)

Sample run -

样品运行 -

In [58]: df
Out[58]: 
   key     value
0   10  10000100
1   20  10000000
2   30  10100000
3   40  11110000

In [59]: arr = df.value.values.astype('S8')

In [60]: pd.DataFrame(np.fromstring(arr, dtype=np.uint8).reshape(-1,8)-48)
Out[60]: 
   0  1  2  3  4  5  6  7
0  1  0  0  0  0  1  0  0
1  1  0  0  0  0  0  0  0
2  1  0  1  0  0  0  0  0
3  1  1  1  1  0  0  0  0

#2


9  

This should work:

这应该工作:

df.value.astype(str).apply(list).apply(pd.Series).astype(int)

根据位数拆分pandas数据帧列

#3


3  

Assuming your input is stored as strings and all have the same length (8, as posed), then the following works:

假设您的输入存储为字符串并且所有输入都具有相同的长度(8,如所示),则以下工作:

df1 = pd.concat([df1,pd.DataFrame(columns=range(8))])
df1[list(range(8))] = df1['Value'].apply(lambda x: pd.Series(list(str(x)),index=range(8)))

#4


2  

A vectorized version would be:

矢量化版本将是:

df['value'].astype(str).str.join(' ').str.split(' ', expand=True)

This first introduces spaces between characters and then splits. It's just a workaround to be able to use str.split (maybe not necessary, not sure). But it is quite faster:

这首先在字符之间引入空格然后分割。这只是一个能够使用str.split的解决方法(可能没有必要,不确定)。但它更快:

df = pd.DataFrame({'value': np.random.randint(10**7, 10**8, 10**4)})

%timeit df['value'].astype(str).str.join(' ').str.split(' ', expand=True)
10 loops, best of 3: 25.5 ms per loop

%timeit df.value.astype(str).apply(list).apply(pd.Series).astype(int)
1 loop, best of 3: 1.27 s per loop

%timeit df['value'].apply(lambda x: pd.Series(list(str(x)),index=range(8)))
1 loop, best of 3: 1.33 s per loop


%%timeit
arr = df.value.values.astype('S8')
pd.DataFrame(np.fromstring(arr, dtype=np.uint8).reshape(-1,8)-48)

1000 loops, best of 3: 1.14 ms per loop

Update: Divakar's solution seems to be the fastest.

更新:Divakar的解决方案似乎是最快的。

#1


3  

One approach could be -

一种方法可能是 -

arr = df.value.values.astype('S8')
df = pd.DataFrame(np.fromstring(arr, dtype=np.uint8).reshape(-1,8)-48)

Sample run -

样品运行 -

In [58]: df
Out[58]: 
   key     value
0   10  10000100
1   20  10000000
2   30  10100000
3   40  11110000

In [59]: arr = df.value.values.astype('S8')

In [60]: pd.DataFrame(np.fromstring(arr, dtype=np.uint8).reshape(-1,8)-48)
Out[60]: 
   0  1  2  3  4  5  6  7
0  1  0  0  0  0  1  0  0
1  1  0  0  0  0  0  0  0
2  1  0  1  0  0  0  0  0
3  1  1  1  1  0  0  0  0

#2


9  

This should work:

这应该工作:

df.value.astype(str).apply(list).apply(pd.Series).astype(int)

根据位数拆分pandas数据帧列

#3


3  

Assuming your input is stored as strings and all have the same length (8, as posed), then the following works:

假设您的输入存储为字符串并且所有输入都具有相同的长度(8,如所示),则以下工作:

df1 = pd.concat([df1,pd.DataFrame(columns=range(8))])
df1[list(range(8))] = df1['Value'].apply(lambda x: pd.Series(list(str(x)),index=range(8)))

#4


2  

A vectorized version would be:

矢量化版本将是:

df['value'].astype(str).str.join(' ').str.split(' ', expand=True)

This first introduces spaces between characters and then splits. It's just a workaround to be able to use str.split (maybe not necessary, not sure). But it is quite faster:

这首先在字符之间引入空格然后分割。这只是一个能够使用str.split的解决方法(可能没有必要,不确定)。但它更快:

df = pd.DataFrame({'value': np.random.randint(10**7, 10**8, 10**4)})

%timeit df['value'].astype(str).str.join(' ').str.split(' ', expand=True)
10 loops, best of 3: 25.5 ms per loop

%timeit df.value.astype(str).apply(list).apply(pd.Series).astype(int)
1 loop, best of 3: 1.27 s per loop

%timeit df['value'].apply(lambda x: pd.Series(list(str(x)),index=range(8)))
1 loop, best of 3: 1.33 s per loop


%%timeit
arr = df.value.values.astype('S8')
pd.DataFrame(np.fromstring(arr, dtype=np.uint8).reshape(-1,8)-48)

1000 loops, best of 3: 1.14 ms per loop

Update: Divakar's solution seems to be the fastest.

更新:Divakar的解决方案似乎是最快的。