在Python中列入列

时间:2016-04-27 13:22:34

标签: python numpy pandas

我有一个CSV文件,其中包含每日降水量的时间序列。问题出在于如何组织数据。这是一个小样本:

date        p01 p02 p03 p04 p05 p06
01-01-1941  33.6 7.1 22.3 0 0 0
01-02-1941  0 0 1.1 11.3 0 0

因此,每月的每一天都有一列(p01是第1天的降水,p02对应于第2天,依此类推)。我希望有这样的结构:迄今为止有一列,另一列有降水值。

date        p
01-01-1941  33.6
02-01-1941  7.1
03-01-1941  22.3
04-01-1941  0
05-01-1941  0
06-01-1941  0
01-02-1941  0
02-02-1941  0
03-02-1941  1.1
04-02-1941  11.3
05-02-1941  0
06-02-1941  0

我找到了一些代码示例,但对于这个特定问题却没有成功。一般来说,他们建议尝试使用熊猫,numpy。有没有人有解决这个问题的建议或指导我的学习的好建议?谢谢。 (对不起我糟糕的英语)

3 个答案:

答案 0 :(得分:2)

我认为您可以首先使用read_csv,然后使用to_datetimestack进行重塑DataFrame,然后转换列days to_timedelta并添加它到列date

import pandas as pd
import io

temp=u"""date;p01;p02;p03;p04;p05;p06
01-01-1941;33.6;7.1;22.3;0;0;0
01-02-1941;0;0;1.1;11.3;0;0"""
#after testing replace io.StringIO(temp) to filename
df = pd.read_csv(io.StringIO(temp), sep=";")
print df
         date   p01  p02   p03   p04  p05  p06
0  01-01-1941  33.6  7.1  22.3   0.0    0    0
1  01-02-1941   0.0  0.0   1.1  11.3    0    0
#convert coolumn date to datetime
df.date = pd.to_datetime(df.date, dayfirst=True)
print df
        date   p01  p02   p03   p04  p05  p06
0 1941-01-01  33.6  7.1  22.3   0.0    0    0
1 1941-02-01   0.0  0.0   1.1  11.3    0    0

#stack, rename columns
df1 = df.set_index('date').stack().reset_index(name='p').rename(columns={'level_1':'days'})
print df1
         date days     p
0  1941-01-01  p01  33.6
1  1941-01-01  p02   7.1
2  1941-01-01  p03  22.3
3  1941-01-01  p04   0.0
4  1941-01-01  p05   0.0
5  1941-01-01  p06   0.0
6  1941-02-01  p01   0.0
7  1941-02-01  p02   0.0
8  1941-02-01  p03   1.1
9  1941-02-01  p04  11.3
10 1941-02-01  p05   0.0
11 1941-02-01  p06   0.0
    
#convert column to timedelta in days
df1.days = pd.to_timedelta(df1.days.str[1:].astype(int) - 1, unit='D')
print df1.days
0    0 days
1    1 days
2    2 days
3    3 days
4    4 days
5    5 days
6    0 days
7    1 days
8    2 days
9    3 days
10   4 days
11   5 days
Name: days, dtype: timedelta64[ns]

#add timedelta
df1['date'] = df1['date'] + df1['days']
#remove unnecessary column
df1 = df1.drop('days', axis=1)
print df1
         date     p
0  1941-01-01  33.6
1  1941-01-02   7.1
2  1941-01-03  22.3
3  1941-01-04   0.0
4  1941-01-05   0.0
5  1941-01-06   0.0
6  1941-02-01   0.0
7  1941-02-02   0.0
8  1941-02-03   1.1
9  1941-02-04  11.3
10 1941-02-05   0.0
11 1941-02-06   0.0

答案 1 :(得分:0)

编辑:抱歉问题的名称有点误导。对于您提供的示例输出(将所有p折叠到一个列中),您可以执行此操作:

# Opening the example file you gave
fid = open('csv.txt','r')
lines = fid.readlines()
fid.close()

fid = open('output2.txt','w')
fid.write('%15s %15s\n'%(lines[0].split()[0],'p'))
for i in range(1,len(lines)):
    iline = lines[i].split()
    for j in range(1,len(iline)):
        fid.write('%15s %15s\n'%(iline[0],iline[j]))
fid.close()

,结果如下:

       date               p
 01-01-1941            33.6
 01-01-1941             7.1
 01-01-1941            22.3
 01-01-1941               0
 01-01-1941               0
 01-01-1941               0
 01-02-1941               0
 01-02-1941               0
 01-02-1941             1.1
 01-02-1941            11.3
 01-02-1941               0
 01-02-1941               0

原始帖子:可能与某人有关。

确实有很多方法可以做到这一点。但是考虑到你没有特别的偏好(如果文件不是很大),你可能只想使用原生Python。

def rows2columns(lines):
    ilines = []
    for i in lines:
        ilines.append(i.split())
    new = []
    for j in range(len(ilines[0])):
        local = []
        for i in range(len(ilines)):
            local.append(ilines[i][j])
        new.append(local)
    return new

def writefile(new,path='output.txt'):
    fid = open(path,'w')
    for i in range(len(new)):
        for j in range(len(new[0])):
            fid.write('%15s'%new[i][j])
        fid.write('\n')
    fid.close()

# Opening the example file you gave
fid = open('csv.txt','r')
lines = fid.readlines()
fid.close()

# Putting the list of lines to be reversed
new = rows2columns(lines)
# Writing the result to a file
writefile(new,path='output.txt')

,输出文件为:

       date     01-01-1941     01-02-1941
        p01           33.6              0
        p02            7.1              0
        p03           22.3            1.1
        p04              0           11.3
        p05              0              0
        p06              0              0

这可能是您可能拥有的最简单(或接近)本机python配方。来自csv模块或numpy或pandas的其他功能将具有您可能希望利用的其他功能。特别是这个不需要进口。

答案 2 :(得分:0)

嗯,我得到了答案,但它没有只有一个命令或任何魔术功能。所以这就是我得到答案的方式。您可以进一步优化此代码。希望这有帮助!

import pandas as pd

from datetime import timedelta


df = pd.read_csv('myfile.csv')

df[u'date'] = pd.to_datetime(df[u'date'])



p1 = df[[u'date', u'p01']].copy()
p2 = df[[u'date', u'p02']].copy()
p3 = df[[u'date', u'p03']].copy()
p4 = df[[u'date', u'p04']].copy()
p5 = df[[u'date', u'p05']].copy()

# renaming cols -p1,p2,p3,p4
p1.columns = ['date','val']
p2.columns = ['date','val']
p3.columns = ['date','val']
p4.columns = ['date','val']
p5.columns = ['date','val']

p1['col'] = 'p01'
p2['col'] = 'p02'
p3['col'] = 'p03'
p4['col'] = 'p04'
p5['col'] = 'p05'


main = pd.concat([p1,p2,p3,p4,p5])


main['days2add'] = main['col'].apply(lambda x: int(x.strip('p')) -1 )

ff = lambda row : row[u'date'] + timedelta(row[u'days2add'])

main['new_date'] = main.apply(ff, axis=1)

In [209]: main[['new_date', u'val']]
Out[209]:
    new_date   val
0 1941-01-01  33.6
0 1941-01-02   7.1
0 1941-01-03  22.3
0 1941-01-04   0.0
0 1941-01-05   0.0

我的csv文件内容:

In [210]: df
Out[210]:
        date   p01  p02   p03  p04  p05  p06
0 1941-01-01  33.6  7.1  22.3    0    0    0

我的输出内容:

In [209]: main[['new_date', u'val']]
Out[209]:
    new_date   val
0 1941-01-01  33.6
0 1941-01-02   7.1
0 1941-01-03  22.3
0 1941-01-04   0.0
0 1941-01-05   0.0