[英]How to split a dataframe column into multiple columns
经过很多尝试之后,我开始将R脚本迁移到Python。 我在R中的大部分工作都涉及数据帧,而我正在使用pandas包中的DataFrame
对象。 在我的脚本中,我需要读取一个csv文件并将数据导入到DataFrame
对象中。 接下来,我需要将十六进制值转换为标记为DATA
的列,再将其转换为按位数据,然后创建16个新列,每个列对应一个。
我在示例test.txt
输入数据的示例如下所示,
前缀,测试,区域,行,颜色,数据
6_6,READ,0,0,0,BFED
6_6,读取,0,1,0,BB7D
6_6,READ,0,2,0,FFF7
6_6,READ,0,3,0,E7FF
6_6,READ,0,4,0,FBF8
6_6,READ,0,5,0,DE75
6_6,READ,0,6,0,DFFE
我的python脚本test.py
如下,
import glob
import pandas as pd
import numpy as np
fname = 'test.txt'
df = pd.read_csv(fname, comment="#")
dfs = df[df.TEST == 'READ']
# function to convert the hexstring into a binary string
def hex2bin(hstr):
return bin(int(hstr,16))[2:]
# convert the hexstring in column DATA to binarystring ROWDATA
dfs['BINDATA'] = dfs['DATA'].apply(hex2bin)
# get rid of the column DATA
del dfs['DATA']
当我运行此脚本并检查dfs
对象时,得到以下信息:
前缀测试区行COL BINDATA
0 6_6读取0 0 0 1011111111101101
1 6_6读取0 1 0 1011101101111101
2 6_6读取0 2 0 1111111111110111
3 6_6读取0 3 0 1110011111111111
4 6_6读取0 4 0 1111101111111000
5 6_6读取0 5 0 1101111001110101
6 6_6读取0 6 0 1101111111111110
所以现在我不确定如何将名为BINDATA
的列BINDATA
为16个新列(可以命名为B0,B0,B2,....,B15)。 任何帮助将不胜感激。
感谢和问候,
Derric。
我不知道它是否可以做得更简单(没有for循环),但这可以解决问题:
for i in range(16):
dfs['B'+str(i)] = dfs['BINDATA'].str[i]
该系列的str
属性可访问对每个元素起作用的一些矢量化字符串方法(请参阅docs: http : //pandas.pydata.org/pandas-docs/stable/basics.html#vectorized-string-methods )。 在这种情况下,我们只需索引字符串即可访问不同的字符。
这给了我:
In [20]: dfs
Out[20]:
BINDATA B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12 B13 B14 B15
0 1011111111101101 1 0 1 1 1 1 1 1 1 1 1 0 1 1 0 1
1 1011101101111101 1 0 1 1 1 0 1 1 0 1 1 1 1 1 0 1
2 1111111111110111 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1
3 1110011111111111 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1
4 1111101111111000 1 1 1 1 1 0 1 1 1 1 1 1 1 0 0 0
5 1101111001110101 1 1 0 1 1 1 1 0 0 1 1 1 0 1 0 1
6 1101111111111110 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 0
如果希望将它们作为整数而不是字符串,则可以在for循环中添加.astype(int)
。
编辑:另一种方法(oneliner,但您必须在第二步中更改列名称):
In [34]: splitted = dfs['BINDATA'].apply(lambda x: pd.Series(list(x)))
In [35]: splitted.columns = ['B'+str(x) for x in splitted.columns]
In [36]: dfs.join(splitted)
Out[36]:
BINDATA B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12 B13 B14 B15
0 1011111111101101 1 0 1 1 1 1 1 1 1 1 1 0 1 1 0 1
1 1011101101111101 1 0 1 1 1 0 1 1 0 1 1 1 1 1 0 1
2 1111111111110111 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1
3 1110011111111111 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1
4 1111101111111000 1 1 1 1 1 0 1 1 1 1 1 1 1 0 0 0
5 1101111001110101 1 1 0 1 1 1 1 0 0 1 1 1 0 1 0 1
6 1101111111111110 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 0
这是没有循环即可执行此操作的方法(但实际上并非如此,因为此代码中有很多隐式循环):
import pandas as pd
# read the above frame from the clipboard
df = pd.read_clipboard(converters={'BINDATA': str})
df = df.fillna(nan).replace('None', nan).dropna(axis=0, how='all')
# here are the lines that matter
bindata = df.BINDATA.apply(list).apply(Series)
bindata.columns = bindata.columns.map('B{0}'.format)
res = pd.concat([df, bindata], axis=1).convert_objects(convert_numeric=True)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.