【问题标题】:Appending data into pandas dataframe将数据附加到熊猫数据框中
【发布时间】:2019-01-14 14:51:23
【问题描述】:

我正在构建一个系统,其中树莓派通过蓝牙接收数据并将其解析为 pandas 数据帧以进行进一步处理。但是,有几个问题。蓝牙数据包被转换为熊猫系列对象,我试图将其附加到空数据帧中,但未成功。下面的拆分是为了从蓝牙数据包中提取遥测数据。

代码用正确的列名创建了一个合适的数据框,但是当我追加到它时,Series 对象的行号变成了新列。每个附加的系列都是最终数据框中的一行。我想知道的是:如何将 Series 对象添加到数据框中,以便将值放入索引从 0 到 6 而不是从 7 到 14 的列中?

编辑:添加了screenshot, 上面输出,下面是pkt的倍数。

Edit2:为每个请求添加了完整代码。添加了错误回溯。

import time
import sys
import subprocess
import pandas as pd
import numpy as np

class Scan:
    def __init__(self, count, columns):
        self.running = True
        self.count = count
        self.columns = columns

    def run(self):
        i_count = 0
        p_data = pd.DataFrame(columns=self.columns, dtype='str')

        while self.running:
            output = subprocess.check_output(["commands", "to", "follow.py"]).decode('utf-8')
            p_rows = output.split(";")
            series_list = []
            print(len(self.columns))

            for packet in p_rows:
                pkt = pd.Series(packet.split(","),dtype='str', index=self.columns)
                pkt = pkt.replace('\n','',regex=True)
                print(len(pkt))
                series_list.append(pkt)
            p_data = pd.DataFrame(pd.concat(series_list, axis=1)).T

            print(p_data.head())
            print(p_rows[0])
            print(list(p_data.columns.values))

            if i_count  == self.count:
                self.running = False
                sys.exit()
            else:
                i_count += 1
            time.sleep(10)

def main():
    columns = ['mac', 'rssi', 'voltage', 'temperature', 'ad count', 't since boot', 'other']
    scan = Scan(0, columns)

while True:
    scan.run()

if __name__ == '__main__':
    main()

Traceback(最近一次调用最后一次): 文件“blescanner.py”,第 48 行,在 主要的() 文件“blescanner.py”,第 45 行,在 main scan.run()

文件“blescanner.py”,第 24 行,运行中 pkt = pd.Series(packet.split(","),dtype='str', index=self.columns)

文件“/mypythonpath/site-packages/pandas/core/series.py”,第 262 行,在 init 中 .format(val=len(data), ind=len(index)))

ValueError: 传递值的长度为 1,索引意味着 7

【问题讨论】:

  • 可能最重要的一点是output的结构。你能告诉我们这是什么样子吗?
  • 请不要添加图片/链接,只添加文字。另请参阅minimal reproducible example
  • 在您的第二次编辑中,您确定您的缩进是正确的吗?如前所述,您的 while 循环将在迭代 p_rows 之前运行完成。我假设for packet in p_rows 应该在您的while self.running 之下

标签: python pandas dataframe append


【解决方案1】:

您不想以这种方式附加到 DataFrame。您可以做的是创建一个系列列表,并将它们连接在一起。

所以,是这样的:

series_list = []
for packet in p_rows:
    pkt = pd.Series(packet.split(","),dtype='str')
    print(pkt)
    series_list.append(pkt)
p_data = pd.DataFrame(pd.concat(series_list), columns=self.columns, dtype='str')

只要在pd.concat调用中不指定ignore_index=True,索引就不会被重置(默认为ignore_index=False

编辑:

您的问题尚不清楚,但如果您尝试将系列添加为新列(而不是彼此堆叠),则将上面的最后一行更改为:

p_data = pd.concat(series_list, axis=1)
p_data.columns = self.columns

编辑2:

仍然不完全清楚,但听起来(从您的编辑中)您希望将系列转置为行,系列的索引成为您的列。即:

series_list = []
for packet in p_rows:
    pkt = pd.Series(packet.split(","), dtype='str', index=self.columns)
    series_list.append(pkt)
p_data = pd.DataFrame(pd.concat(series_list, axis=1)).T

编辑 3: 根据您的输出图片,当您拆分 ; 时,列表中的最后一个元素为空。例如:

output = """f1:07:ad:6b:97:c8,-24,2800,23.00,17962365,25509655,None;
            f1:07:ad:6b:97:c8,-24,2800,23.00,17962365,25509655,None;"""

output.split(';')

['f1:07:ad:6b:97:c8,-24,2800,23.00,17962365,25509655,None',
 '\n            f1:07:ad:6b:97:c8,-24,2800,23.00,17962365,25509655,None',
 '']

所以不要for packet in p_rowsfor packet in p_rows[:-1]

完整示例:

columns = ['mac', 'rssi', 'voltage', 'temperature', 'ad count', 't since boot', 'other']

output = """f1:07:ad:6b:97:c8,-24,2800,23.00,17962365,25509655,None;
            f1:07:ad:6b:97:c8,-24,2800,23.00,17962365,25509655,None;"""
p_rows = output.split(";")
series_list = []

for packet in p_rows[:-1]:
    pkt = pd.Series(packet.strip().split(","), dtype='str', index=columns)
    series_list.append(pkt)
p_data = pd.DataFrame(pd.concat(series_list, axis=1)).T

生产

                 mac rssi voltage temperature  ad count t since boot other
0  f1:07:ad:6b:97:c8  -24    2800       23.00  17962365     25509655  None
1  f1:07:ad:6b:97:c8  -24    2800       23.00  17962365     25509655  None

【讨论】:

  • 每个系列对应数据框中的一行,将相应地进行编辑。
  • 那么,每个系列都是由多列组成的一行?
  • 是的,因此进行拆分,逗号之间的每个值都被发送到数据框中自己的列。
  • 好的,见编辑#2。这应该达到你想要的。您不想像现在这样在循环中附加到 DataFrame,因为每个附加都会复制整个 DataFrame,随着 DataFrame 大小的增长,效率会降低。
  • 非常感谢,现在可以使用了!我想中间的一个小strip() 把它们粘在一起了。
【解决方案2】:

这是因为追加语句中 p_data df 和 pkt 数据之间的键冲突 - 您需要确保 pkt 中的键与您要追加到的 p_data 数据框中的列标题相匹配.

通过将 p_data 数据框中的列重命名为您在 pkt 中看到的数字,或在附加数据之前重命名 pkt 中的键来解决此问题。

编辑:经过进一步讨论,商定的列名将不会出现在其中,因为传入的数据与现有 df 的顺序相同。只需将pd.DataFrame() 包裹在pkt 对象周围,并确保追加时数据行的形状正确,即可获得所需的结果。

import pandas as pd
import numpy as np

# Set initial df with data
d = pd.DataFrame(['f1:07:ad:6b:97:c8', '-23', '2900', '24.00', '17962371', '25509685', 'None']).T
p_data = pd.DataFrame(data=d, dtype='str')

# Parse new incoming data
output = "f1:07:ad:6b:97:c8;-24;2800;23.00;17962365;25509655;None"
pkt = output.split(";")

# Append new data to existing dataframe
p_data = p_data.append(pd.DataFrame(data=p_rows).T, ignore_index=True)

【讨论】:

  • 我想到了,但是,我收到一个类型错误,说除非 ignore_index=True,否则无法附加系列。
  • @Minregx 明白了,我的解决方案是将pkt 系列转换为df,然后追加。您可以内联执行此操作(示例中的第 10 行)-有关更多详细信息,请参阅此答案:stackoverflow.com/a/37909639/3446927
猜你喜欢
  • 2018-02-08
  • 2017-06-13
  • 2014-01-03
  • 1970-01-01
  • 2021-09-24
  • 2022-11-25
  • 2019-10-22
  • 2018-05-24
  • 1970-01-01
相关资源
最近更新 更多