我有一个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。有没有人有解决这个问题的建议或指导我的学习的好建议?谢谢。 (对不起我糟糕的英语)
答案 0 :(得分:2)
我认为您可以首先使用read_csv
,然后使用to_datetime
和stack
进行重塑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