【发布时间】:2017-10-23 14:21:28
【问题描述】:
我正在处理许多不同的 csv 文件,这些文件以 pandas 数据帧的形式读取,然后从中提取有趣的索引和数据,并将其收集到一个新的数据帧中,我逐行构建然后保存。每一行代表一个文件中的信息。
原始数据帧以毫秒精度的纪元时间为索引。虽然时间是不必要的精确,但我无法改变它。
>>> df.index
Int64Index([1382441313687, 1382441314687, 1382441315687, 1382441316687,
1382441317687, 1382441318687, 1382441319687, 1382441320687,
1382441321687, 1382441322687,
...
1382445583687, 1382445584687, 1382445585687, 1382445586687,
1382445587687, 1382445588687, 1382445589687, 1382445590687,
1382445591687, 1382445592687],
dtype='int64', name=u'time', length=4280)
我通过构建一个有趣的值列表并从中创建一个系列来构建新的数据框,然后我将其附加到数据框。
columns = ['Start time', 'End time']
summary = pd.DataFrame(columns=columns)
for i, df in enumerate(long_list_of_dfs):
start_time = df.index[0]
end_time = df.index[-1]
data = [start_time, end_time]
new_line = pd.Series({key:val for key, val in zip(columns, data)})
summary = summary.append(new_line)
summary.to_csv(out_dir)
我使用摘要中保存的索引来快速索引原始数据框中的有趣点。但是,在构建新数据框时,会丢失一些精度,我最终得到以下结果:
>>> for line in open(out_dir):
... print(line)
,Start time,End time
0,1.38244131369e+12,138244559269e+12
再次阅读此摘要时,我无法再使用这些值来索引原始数据帧,因为它会导致 KeyError。直接构建数据框时不会发生这种情况:
>>> summary2 = pd.DataFrame({'Start time':[1382441313687], 'End time':[1382445592687]})
>>> summary2
End time Start time
0 1382445592687 1382441313687
>>> summary2.to_csv(out_dir)
>>> for line in open(out_dir):
... print(line)
,Start time,End time
0,1382441313687,1382445592687
有人知道为什么会发生这种转换吗?我知道我可以指定数据类型,但我有很多不同数据类型的列,宁愿省去麻烦。我觉得如果这些值保持原始格式也会更直观。
编辑 我想强调的是,我在 for 循环中构建了 Dataframe,因为我有很多我想为每行添加的数据点。此外,原始数据帧的数量相当多(约 90.000 个文件 @ 每个 20MB),所以我只想打开每个文件一次。
上面的代码只是一个工作示例,表明尽管数据是整数,但最后两位数字被四舍五入,大概在附加行中。 new_line 系列仍保留原始格式的数据,直到最后两位数。
下面是前 10 行的 summary.info() 的输出。如您所见,有些列包含 NaN,但也有一些不包含。我希望没有 NaN 的列保留它们的整数格式。
>>> summary.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 88158 entries, 0 to 88157
Data columns (total 46 columns):
Date added 88158 non-null object
Filename 88158 non-null object
ACID 88158 non-null int64
FLID 88158 non-null int64
Flag 88158 non-null object
L ESN 86986 non-null float64
R ESN 86986 non-null float64
Start time 88158 non-null float64
End time 88158 non-null float64
Total duration 88158 non-null float64
EDIT2 这是另一个简短的示例,用于显示我在使用长整数逐行构建数据帧时遇到的问题。
>>> df = pd.DataFrame(columns=['a', 'b'])
>>> df.loc[len(df.index)] = [1382441313687, 1382441314687]
>>> df
a b
0 1.382441e+12 1.382441e+12
>>> df.loc[0, 'a']
1382441313687.0 # Correct data!
>>> df.to_csv(out_dir)
>>> for line in open(out_dir):
... print(line)
,a,b
0,1.38244131369e+12,1.38244131469e+12 # Not correct! 1382441313690 != 1382441313687
【问题讨论】:
-
你能给
summary.info()可能有一些NaNs 并且这些列被转换为浮动 -
我在问题中添加了
summary.info()的前十行。如您所见,尽管没有空值,但仍有一些行被转换为浮点数。 -
为什么不把
Start time等列转换成Timestamp,这样就不会有精度损失 -
如果没有更好的解决方案,我会考虑这个解决方案。不过,我宁愿使用纪元时间。
-
我的摘要生成器方法有什么问题?而不是
s = [df[k].mean() for k in columns],你可以按照你想要的方式总结它而不会出现问题