【问题标题】:Appending Rows to a Pandas DataFrame将行附加到 Pandas DataFrame
【发布时间】:2017-05-03 22:52:51
【问题描述】:

我正在尝试从测量计算个人测量设备 (PMD-1208FS) 中读取模拟信号,然后将其写入文件中,并为每个观察提供相应的时间戳。我想每秒一次附加到这个文件中,并进行新的观察。

PyUniversalLibrary 允许我从设备中读取数据,但我一直在试图弄清楚如何将信息保存到数据框中。这个example 有助于从 PMD 读取数据,但它不提供任何数据记录示例。

下面的例子接近解决这个问题,但是df.append(pd.DataFrame() 函数没有为我提供想要的结果。此函数最终将最新的数据帧附加到先前保存的数据帧的底部,而不仅仅是附加新数据。结果是一个数据帧,其中包含许多按顺序重复的数据帧。

这是我的代码:

## Source libraries:
from __future__ import print_function
import UniversalLibrary as UL
import time, os, io, csv, datetime
import pandas as pd

## Specify PMD settings:
BoardNum = 0
Gain = UL.BIP5VOLTS
Chan = 0

## Create empty lists and a dataframe to fill:
co = [] ## carbon monoxide concentration in ppm
data = [] ## raw analog output between 0-5V
times = [] ## timestamp
df = pd.DataFrame()


## Set filepath:
filename = "~/pmd_data.csv"

while True:
    ts = time.time()
    DataValue = UL.cbAIn(BoardNum, Chan, Gain)
    EngUnits = UL.cbToEngUnits(BoardNum, Gain, DataValue)
    ppm = EngUnits * 10 ## 1 Volt = 10ppm of carbon monoxide
    data.append(EngUnits)
    times.append(datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S'))
    co.append(ppm)
    ## This line of code is not providing the desired result:
    df = df.append(pd.DataFrame({'co':ppm, 'volts':data, 'datetime':times})) 
    print(df)
    df.to_csv(filename, sep = ',', index = False, encoding = 'utf-8')
    time.sleep(1)

电流输出:

    co    datetime    volts
0    13.8    2017-05-03 15:57:19   1.38
1    13.8    2017-05-03 15:57:19   1.38    
2    13.9    2017-05-03 15:57:20   1.39
3    13.8    2017-05-03 15:57:19   1.38
4    13.9    2017-05-03 15:57:20   1.39
5    14.2    2017-05-03 15:57:21   1.42

期望的输出:

    co    datetime    volts
0    13.8    2017-05-03 15:57:19   1.38
1    13.9    2017-05-03 15:57:20   1.39
2    14.2    2017-05-03 15:57:21   1.42

【问题讨论】:

    标签: python pandas numpy data-acquisition


    【解决方案1】:

    如果您只是想追加,那么您不需要带有 .loc 的计数器。您可以将其更改为 df.loc[len(df)] = row 。这将始终在 DataFrame 的末尾写入一个新行。

    这里从 piRSquared 代码更新了代码:

    ## Source libraries:
    from __future__ import print_function
    import UniversalLibrary as UL
    import time, os, io, csv, datetime
    import pandas as pd
    
    ## Specify PMD settings:
    BoardNum = 0
    Gain = UL.BIP5VOLTS
    Chan = 0
    
    ## Create empty lists and a dataframe to fill:
    df = pd.DataFrame(columns=['co', 'volts', 'datetime'])
    
    ## Set filepath:
    filename = "~/pmd_data.csv"
    
    while True:
        ts = time.time()
        DataValue = UL.cbAIn(BoardNum, Chan, Gain)
        EngUnits = UL.cbToEngUnits(BoardNum, Gain, DataValue)
        ppm = EngUnits * 10 ## 1 Volt = 10ppm of carbon monoxide
        df.loc[len(df)] = pd.Series(dict(
                co=ppm, volts=EngUnits, datetime=ts
            ))
        ## This line of code is not providing the desired result:
        df.to_csv(filename, sep = ',', index = False, encoding = 'utf-8')
        time.sleep(1)
    

    【讨论】:

      【解决方案2】:

      由于您不专门使用索引,我会保留一个计数器并使用它向现有数据框添加新行。

      我会像这样重写while 循环

      ## Source libraries:
      from __future__ import print_function
      import UniversalLibrary as UL
      import time, os, io, csv, datetime
      import pandas as pd
      
      ## Specify PMD settings:
      BoardNum = 0
      Gain = UL.BIP5VOLTS
      Chan = 0
      
      ## Create empty lists and a dataframe to fill:
      df = pd.DataFrame(columns=['co', 'volts', 'datetime'])
      
      ## Set filepath:
      filename = "~/pmd_data.csv"
      
      counter = 0
      while True:
          ts = time.time()
          DataValue = UL.cbAIn(BoardNum, Chan, Gain)
          EngUnits = UL.cbToEngUnits(BoardNum, Gain, DataValue)
          ppm = EngUnits * 10 ## 1 Volt = 10ppm of carbon monoxide
          df.loc[counter] = pd.Series(dict(
                  co=ppm, volts=EngUnits, datetime=ts
              ))
          ## This line of code is not providing the desired result:
          counter += 1
          df.to_csv(filename, sep = ',', index = False, encoding = 'utf-8')
          time.sleep(1)
      

      【讨论】:

      • 这成功了!非常感谢你的帮助!我是 python 新手,这教会了我如何以一种我不会忘记的方式使用 columnsdf.loc[counter]。对于将输出打印到控制台的最佳方式,您有什么快速建议吗?我目前正在使用print(df.loc[counter]),但输出以长格式而不是所需的宽格式堆叠我的列。我现在能够从一台 20 岁以上的空气质量仪器获取数据!再次感谢!
      • @spacedSparking 很高兴我可以为该乐器增添活力。试试print(df.loc[[counter]])
      【解决方案3】:

      每次进入 while 循环时,您都在为每个字段附加一个带有列表(随时间增长)的数据框。但是您应该添加一个数据框,其中包含一个列表,每个字段一次只有一个元素。请看下面的例子

      你实际上是在这样做:

      co = [] ## carbon monoxide concentration in ppm
      data = [] ## raw analog output between 0-5V
      times = [] ## timestamp
      
      df = pd.DataFrame()
      for i in range(0,5):
          data.append(i)
          times.append(i)
          co.append(i)
          df = df.append(pd.DataFrame({'co':co, 'volts':data, 'datetime':times}))
      print df
      

      导致

         co  datetime  volts
      0   0         0      0
      0   0         0      0
      1   1         1      1
      0   0         0      0
      1   1         1      1
      2   2         2      2
      0   0         0      0
      1   1         1      1
      2   2         2      2
      3   3         3      3
      0   0         0      0
      1   1         1      1
      2   2         2      2
      3   3         3      3
      4   4         4      4
      

      但你应该这样做

      df = pd.DataFrame()
      for i in range(0,5):
          df = df.append(pd.DataFrame({'co':[i], 'volts':[i], 'datetime':[i]}))
      print df
      

      导致

         co  datetime  volts
      0   0         0      0
      0   1         1      1
      0   2         2      2
      0   3         3      3
      0   4         4      4
      

      所以你的代码应该像

      ## Source libraries:
      from __future__ import print_function
      import UniversalLibrary as UL
      import time, os, io, csv, datetime
      import pandas as pd
      
      ## Specify PMD settings:
      BoardNum = 0
      Gain = UL.BIP5VOLTS
      Chan = 0
      
      ## Create empty dataframe to fill:
      df = pd.DataFrame()
      
      ## Set filepath:
      filename = "~/pmd_data.csv"
      
      while True:
          ts = time.time()
          DataValue = UL.cbAIn(BoardNum, Chan, Gain)
          EngUnits = UL.cbToEngUnits(BoardNum, Gain, DataValue)
          ppm = EngUnits * 10 ## 1 Volt = 10ppm of carbon monoxide
          times = (datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S'))
          df = df.append(pd.DataFrame({'co':[ppm], 'volts':[EngUnits], 'datetime':[times]})) 
          print(df)
          df.to_csv(filename, sep = ',', index = False, encoding = 'utf-8')
          time.sleep(1)
      

      【讨论】:

      • 感谢您的意见。我真的需要 while 循环来为这个应用程序工作,因为我没有提前知道我的数据范围。
      • 很高兴为您提供帮助。我只是使用 for 循环作为演示,您仍然可以使用您的 while 循环。查看我的最新编辑。
      猜你喜欢
      • 2014-05-19
      • 2015-03-06
      • 1970-01-01
      • 2018-11-30
      • 2013-08-14
      • 1970-01-01
      • 2019-06-08
      • 2019-05-21
      • 1970-01-01
      相关资源
      最近更新 更多