Python - 从输出中生成数据框而不知道列键

2024-09-30 18:33:30 发布

您现在位置:Python中文网/ 问答频道 /正文

如果我想从CLI输出创建dataframe,但不知道其中的列键,
我只知道键结束的原始位置(从原始数字0开始)和键之间的分隔符(\s+)。你知道吗

在这种情况下,有没有快速而好的方法从输出中找到(生成)dataframe的列键?你知道吗

例如:

                                                                                 MODIFIED

CORE SERVER         ACTIVE                         PASSIVE                       PACKAGES

------------------  ------------------------------ ----------------------------- --------

cs010               1.9.2.0-2+auto166              1.9.2.0-2+auto146             no      

它应该生成以下键列表:CORE SERVER , ACTIVE , PASSIVE , MODIFIED PACKAGES


Tags: 方法coredataframecliserverpackages情况数字
2条回答

假设我理解正确,您可以拆分包含所有列名的字符串输入(用空格分隔),然后使用列表理解构建一个字典,然后从中生成一个空数据帧。你知道吗

import pandas as pd

string="""
                                                                                MODIFIED

CORE SERVER         ACTIVE                         PASSIVE                       PACKAGES

                                         -     

cs010               1.9.2.0-2+auto166              1.9.2.0-2+auto146             no
"""
string = string.split("-")[0]

col_names ={name:[ ] for name in re.split(r"\s\s+", string) 
    if name is not ""}

df = pd.DataFrame(col_names)
print(col_names)
print(df)

# with output below:
{'MODIFIED': [], 'CORE SERVER': [], 'ACTIVE': [], 'PASSIVE': [], 'PACKAGES': []}
Empty DataFrame
Columns: [MODIFIED, CORE SERVER, ACTIVE, PASSIVE, PACKAGES]
Index: []

正则表达式拆分的文档在这里:re.split()如果您想使用正则表达式。你知道吗

因为您有行输出,可以在行中加倍,但似乎有连字号指示列大小,您可以使用类似于:

import re
import pandas as pd

string="""
                                                                                 MODIFIED
CORE SERVER         ACTIVE                         PASSIVE                       PACKAGES

                                         -     

cs010               1.9.2.0-2+auto166              1.9.2.0-2+auto146             no
"""

rows = [row for row in re.split(r"\n|\r", string)]
for row in rows:
    if " -" in row:
        # get all of the splits below columns
        indices = [i for i,j in enumerate(row) if j.isspace()]
        # After you find the column width stop checking rows.
        break

indices.insert(0, 0)
matrix = [ ]
for row in rows:
    # from your output, hyphens show where headers stop
    if " -" in row:
        break
    matrix.append([row[i:j] for i,j in zip(indices, indices[1:]+[None])])

n = (len(indices))
col_names = [""]*n

for i in range(n):
    for row in matrix:
        col_names[i] += row[i]
    col_names[i] = col_names[i].strip()

df = pd.DataFrame(columns=[c for c in col_names if c is not ''])
print(df)

# with output:
Empty DataFrame
Columns: [CORE SERVER, ACTIVE, PASSIVE, MODIFIED PACKAGES]
Index: []

这段代码不是有史以来最有效的东西,但可以完成任务,不需要添加许多函数。你知道吗

好的。你知道吗

我创建了自己的函数来生成它,并且它可以工作。你知道吗

def auto_generate_dataframe_columns(output, raw_separtor=" -", col_seperator=r'\s{2,}'):
    """Automatically generate dataframe columns.

    :param output: output for generating columns from
    :param raw_separtor: keys raw seperator symbol
    :param col_seperator: columns raw separator symbol (default separator is double or more spaces)
    :return: list with generated keys in case of success otherwise None
    """
    if output is None:
        return None
    keys_lines_list = []
    pattern = re.compile(col_seperator)
    for line in output.splitlines():
        if raw_separtor in line:
            break
        curr_line = line.lstrip()
        curr_line = pattern.split(curr_line)
        if not is_line_empty(curr_line):
            curr_line = [x for x in curr_line if x]
            keys_lines_list = merge_two_lists(keys_lines_list, curr_line)
    return keys_lines_list


def merge_two_lists(list1, list2):
    """Function for merging to lists to one list
    :param list1: first list item
    :param list2: second list item
    :return: merged list
    """
    max_len = list2.__len__() if [list1.__len__() < list2.__len__()] else list1.__len__()
    rev_new_list = []
    for index in range(max_len):
        index1 = list1.__len__() - index - 1
        index2 = list2.__len__() - index - 1
        if index1 < 0:
            rev_new_list.append(list2[max_len - index - 1])
        elif index2 < 0:
            rev_new_list.append(list1[max_len - index - 1])
        else:
            rev_new_list.append(list1[list1.__len__() - index - 1] + " " + list2[list2.__len__() - index - 1])
    return rev_new_list[::-1]


def is_line_empty(line):
    """Function for checking if line is empty

    :param line: given line
    :return: True if line is empty otherwise False
    """
    if not line or (len(line) == 0) or (len(line) == 1 and line[0] == ""):
        return True
    return False

相关问题 更多 >