当前位置: 代码迷 >> python >> 如何使用Pandas转换器将数据框列拆分为多列
  详细解决方案

如何使用Pandas转换器将数据框列拆分为多列

热度:115   发布时间:2023-06-16 14:13:30.0

我有一个带有这样的行的文件:

blablabla (CODE1513A15), 9.20, 9.70, 0

我希望熊猫能够读取每一列,但是从第一列开始,我只对方括号之间的数据感兴趣,并且希望将其提取到其他列中。 因此,我尝试使用Pandas转换器:

import pandas as pd
from datetime import datetime
import string

code = 'CODE'
code_parser = lambda x: {
    'date': datetime(int(x.split('(', 1)[1].split(')')[0][len(code):len(code)+2]), string.uppercase.index(x.split('(', 1)[1].split(')')[0][len(code)+4:len(code)+5])+1, int(x.split('(', 1)[1].split(')')[0][len(code)+2:len(code)+4])), 
    'value': float(x.split('(', 1)[1].split(')')[0].split('-')[0][len(code)+5:])
}
column_names = ['first_column', 'second_column', 'third_column', 'fourth_column']
pd.read_csv('myfile.csv', usecols=[0,1,2,3], names=column_names, converters={'first_column': code_parser})

使用此代码,我可以将方括号之间的文本转换为包含日期时间对象和值的字典。

如果如示例中的代码是CODE1513A15,它将从以下位置构建:

  • 已知代码(在此示例中为“ CODE”)
  • 年的两位数
  • 月份中的两位数字
  • 从A到L的字母,即月(A代表一月,B代表二月,...)
  • 浮点值

我测试了lambda函数,它正确地提取了我想要的信息,其输出是dict {'date': datetime(15, 1, 13), 'value': 15} 不过,如果我打印pd.read_csv方法的结果,则“ first_column”是一个命令,而我希望它会被称为“ date”和“ value”的两列替换:

                         first_column  second_column  third_column  fourth_column
0   {u'date':13-01-2015, u'value':15}           9.20          9.70              0
1   {u'date':14-01-2015, u'value':16}           9.30          9.80              0
2   {u'date':15-01-2015, u'value':12}           9.40          9.90              0

我想要得到的是:

               date  value  second_column  third_column  fourth_column
0        13-01-2015     15           9.20          9.70              0
1        14-01-2015     16           9.30          9.80              0
2        15-01-2015     12           9.40          9.90              0

注意:我不在乎日期的格式,这只是我所期望得到的一种表示。

任何想法?

我认为最好一步一步做。

# read data into a data frame
column_names = ['first_column', 'second_column', 'third_column', 'fourth_column']
df = pd.read_csv(data, names=column_names)

# extract values using regular expression which is much more robust
# than string spliting
tmp = df.first_column.str.extract('CODE(\d{2})(\d{2})([A-L]{1})(\d+)')
tmp.columns = ['year', 'day', 'month', 'value']
tmp['month'] = tmp['month'].apply(lambda m: str(ord(m) - 64))

样本输出:

print tmp 
  year day month value
0   15  13     1    15

然后将原始数据帧转换为所需的格式

df['date'] = (tmp['year'] + tmp['day'] + tmp['month']).apply(lambda d: strptime(d, '%y%d%m'))
df['value'] = tmp['value']
del df['first_column']

是否必须在read_csv转换? 否则,传递一个返回Series的函数以apply结果applyDataFrame

df 
              first_column  second_column  third_column  fourth_column
0  blablabla (CODE1513A15)            9.2           9.7              0
1  blablabla (CODE1514A16)            9.2           9.7              0

code_parser = lambda x: pd.Series({
    'date': datetime(2000+int(x.split('(', 1)[1].split(')')[0][len(code):len(code)+2]), string.uppercase.index(x.split('(', 1)[1].split(')')[0][len(code)+4:len(code)+5])+1, int(x.split('(', 1)[1].split(')')[0][len(code)+2:len(code)+4])), 
    'value': float(x.split('(', 1)[1].split(')')[0].split('-')[0][len(code)+5:])
})

df['first_column'].apply(code_parser)
        date  value
0 2015-01-13     15
1 2015-01-14     16
  相关解决方案