Pandas数据框浮点索引和转置错误

0 投票
2 回答
2047 浏览
提问于 2025-04-18 16:57

我正在尝试将一个用空格分隔的数据文件正确导入到pandas的数据框中,这样我才能正确地绘制图表。我的数据文件长这样:

Vmeas   -5.00E+000  -4.50E+000  -4.00E+000  -3.50E+000 ...
vfd3051 -3.20E-008  -1.49E-009  1.38E-008   -1.17E-008 ...
vfd3151 -3.71E-008  -6.58E-009  -6.58E-009  -6.58E-009 ...
vfd3251 -4.73E-008  3.59E-009   8.68E-009   -1.68E-008 ...
vfd3351 -2.18E-008  -3.71E-008  3.60E-009   -3.20E-008 ...

所以测试位置最开始是在行中,列的电压从左到右增加,直到20V。

我用来读取数据文件到数据框的代码是:

if __name__ == '__main__':
    file_path = str(input("Enter the filename to open:  "))
    save = str(input('Do you wish to save a pdf of the IV plots? (y/n): '))
    df = pd.read_csv(file_path, index_col="Vmeas", delim_whitespace=True, header=0)
    df = df.T
    df.reset_index(inplace=True)
    df.index.names = ['Voltage']
    df.columns.names = ['Die_numbers']
    df.drop('index',axis=1, inplace=True)
    make_plots(df, save)

实际绘图的代码是:

def make_plots(df, save):
    voltage = np.arange(-5, 20, 0.5)
    plt.figure(figsize=(10, 7))
    for col in df:
        plt.plot(voltage, col, legend=False)
    plt.show()

一开始,我遇到的问题是pandas把电压当成了字符串,而pandas对浮点数索引不太友好。最开始尝试的时候,我的二极管电流-电压关系图从0开始绘制。(https://i.stack.imgur.com/i2XOY.jpg) 然后,我重新设置了索引,但绘图还是不行。现在,我重新设置了数据框的索引,删除了旧的索引列,当我检查df.head()时,一切看起来都正常:

Die_numbers       vfd3051       vfd3151           vfd3251          vfd3351  
Voltage                                                               
0                -3.202241e-08 -3.711351e-08 -4.728576e-08 -2.184733e-08   
1                -1.493095e-09 -6.580329e-09  3.594383e-09 -3.710431e-08   
2                 1.377107e-08 -6.581644e-09  8.683344e-09  3.595368e-09 

但现在我在mpl中不断遇到ValueError。我觉得这和列的值是字符串而不是浮点数有关,我不明白为什么,因为之前电流打印得很好。

老实说,我对pandas还很陌生,但似乎每次我都被自己的无知阻碍,真让人疲惫。有没有更好的方法?也许我应该忽略日志文件的第一行?在读取文件时能否转换科学计数法?继续努力吗?

谢谢。

df.info()的结果是:

Int64Index: 51 entries, 0 to 50
Columns: 1092 entries, vfd3051 to vfd6824
dtypes: float64(1092)

一切似乎都正确加载到pandas中,但mpl对数据中的某些东西不满意。列是浮点数,我没有使用整数索引。如果列名被当作第一行添加,列就会被当作字符串或对象类型。错误是:

 Traceback (most recent call last):
  File "D:\Python\el_plot_top_10\IV_plot_all.py", line 51, in <module>
    make_plots(df, save)
  File "D:\Python\el_plot_top_10\IV_plot_all.py", line 21, in make_plots
    plt.plot(voltage, col, legend=False)
  File "C:\Anaconda3\lib\site-packages\matplotlib\pyplot.py", line 2987, in plot
    ret = ax.plot(*args, **kwargs)
  File "C:\Anaconda3\lib\site-packages\matplotlib\axes.py", line 4139, in plot
    for line in self._get_lines(*args, **kwargs):
  File "C:\Anaconda3\lib\site-packages\matplotlib\axes.py", line 319, in _grab_next_args
    for seg in self._plot_args(remaining, kwargs):
  File "C:\Anaconda3\lib\site-packages\matplotlib\axes.py", line 278, in _plot_args
    linestyle, marker, color = _process_plot_format(tup[-1])
  File "C:\Anaconda3\lib\site-packages\matplotlib\axes.py", line 131, in _process_plot_format
    'Unrecognized character %c in format string' % c)
ValueError: Unrecognized character f in format string

2 个回答

-1

从我看到的情况来看,你的问题主要是因为一开始没有把数据整理成正确的格式。你只需要专注于导入数据,并打印出你要绘图的数据,检查一下数据类型是否符合你的预期。

我建议你换一种方法来导入数据,因为这个文件格式并不是pandas最擅长处理的(比如,它是转置的)。例如,你可以使用 numpy.genfromtxt,这里有一个简单的介绍 在这里

import numpy as np
from StringIO import StringIO 

data_file = (
"""Vmeas   -5.00E+000  -4.50E+000  -4.00E+000  -3.50E+000
vfd3051 -3.20E-008  -1.49E-009  1.38E-008   -1.17E-008
vfd3151 -3.71E-008  -6.58E-009  -6.58E-009  -6.58E-009
vfd3251 -4.73E-008  3.59E-009   8.68E-009   -1.68E-008
vfd3351 -2.18E-008  -3.71E-008  3.60E-009   -3.20E-008
""")

data = np.genfromtxt(StringIO(data_file), dtype=None)

print data

>>> array([('Vmeas', -5.0, -4.5, -4.0, -3.5),
       ('vfd3051', -3.2e-08, -1.49e-09, 1.38e-08, -1.17e-08),
       ('vfd3151', -3.71e-08, -6.58e-09, -6.58e-09, -6.58e-09),
       ('vfd3251', -4.73e-08, 3.59e-09, 8.68e-09, -1.68e-08),
       ('vfd3351', -2.18e-08, -3.71e-08, 3.6e-09, -3.2e-08)], 
      dtype=[('f0', 'S7'), ('f1', '<f8'), ('f2', '<f8'), ('f3', '<f8'), ('f4', '<f8')])

现在我们得到了一个包含元组的numpy数组,第一项是列名,后面的项是所有的数据。最重要的是,所有的数字都是数字,尽量避免使用字符串,因为转换起来会很麻烦。

接下来,我们可以做以下操作来得到一个漂亮的 pandas DataFrame

DataDictionary = {row[0]:list(row)[1:] for row in iter(data)}
pd.DataFrame(DataDictionary)

首先,我们通过使用 Python字典推导式 创建一个数据字典,然后将这个字典传入 DataFrame。这样就得到了一个表现良好的数据框,列名分别是 "Vmeas"、"vdf*",并且有所有数据的索引。

    Vmeas   vfd3051          vfd3151         d3251          vfd3351
0   -5.0    -3.200000e-08   -3.710000e-08   -4.730000e-08   -2.180000e-08
1   -4.5    -1.490000e-09   -6.580000e-09   3.590000e-09    -3.710000e-08
2   -4.0    1.380000e-08    -6.580000e-09   8.680000e-09    3.600000e-09
3   -3.5    -1.170000e-08   -6.580000e-09   -1.680000e-08   -3.200000e-08

我怀疑这不能完全解决你的问题,但这是在绘图之前整理数据的一个开始,我觉得这正是你遇到的问题。尽量保持简单!

0

我找到了一个完全在pandas中工作的办法。首先,不要指定索引或表头行。接着,把数据框转置,并去掉索引。然后,从第一行数据中创建一个列表,这个列表将成为你想要的列名。把这些列名赋值给这个列表,然后重新把数据框赋值为一个切片数据框,去掉第一行的字符串名称(在我的例子中是'vfd3021')。

之后,你就可以开始了。列的数据类型是浮点数,因为我的电压范围是固定的,所以在绘图时我只需用arange创建一个列表。

if __name__ == '__main__':
    file_path = str(input("Enter the filename to open:  "))
    save = str(input('Do you wish to save a pdf of the IV plots? (y/n): '))

    df = pd.read_csv(file_path, delim_whitespace=True)

    df = df.T
    df.reset_index(inplace=True)
    df.index.names = ['Voltage']
    df.columns.names = ['Die_numbers']
    df.drop('index', axis=1, inplace=True)
    names = df.iloc[0].values
    df.columns = names
    df = df[1:]
    make_plots(df, save)

撰写回答