【问题标题】:Separate text from a csv row into multiple ones?将csv行中的文本分成多个?
【发布时间】:2018-07-27 04:18:46
【问题描述】:

我有一个 .csv 文件,其中包含以下行:NAMELOCATIONIP AddressIP Address 行中有许多 IP,它们由空格分隔,最多 5 个字符。例如:

编辑:

Name,Location,IP Address
Router,China,10.10.10.1     10.10.10.2     10.10.10.3     10.10.10.4     10.10.10.5
Switch,USA,192.168.1.1     192.168.1.2     192.168.1.3

等等..

我希望所有 IP 都位于 IP Address 列下的单独行中。这就是我希望输出的样子:

Name,Location,IP Address
Router,China,10.10.10.1
Router,China,10.10.10.2
Router,China,10.10.10.3
Router,China,10.10.10.4
Router,China,10.10.10.5
Switch,USA,192.168.1.1
Switch,USA,192.168.1.2
Switch,USA,192.168.1.3

我一直在尝试做.split(),但它给了我一个错误。谁能帮帮我?

使用csv.DictReader 在此处读取我的 csv 文件。

【问题讨论】:

  • @FlorianWeimer 糟糕,我在编辑时犯了一个错误。但是这些 IP 之间的所有空格都是 5 个字符的空格。只需将它们视为 3 个不同的列。
  • @FlorianWeimer 是的,它只是一个普通的 csv,我手动编辑了它,这就是它变得有点难以理解的原因。
  • 第二个@FlorianWeimer 的观点,如果您的数据是空格分隔的,那么一种解决方案是合适的。如果它是固定宽度,另一个是合适的。如果它实际上像您的问题现在显示的那样有逗号,那么一种完全不同的方法将起作用。毫不奇怪,在处理数据时,精确的数据格式很重要
  • Karan:只需在文本编辑器中打开 csv 文件,然后将其复制并粘贴到您的问题中。还要具体说明发生的错误。
  • @martineau 知道了!我从来不知道如何像这样将 csv 数据放在 SO 上,我的错,我没有正确阅读规则。我现在已经编辑了。 :)

标签: python python-3.x csv


【解决方案1】:

基本思想是将 IP 地址字符串及其空格拆分成一个包含 IP 地址列表/数组的列表。然后将其分解为长格式,而每个组合(值)都表示为一行。我通过使用 Pandas DataFrame 及其 groupby 函数和自定义 apply 函数一步完成了这一点。对于您的问题,此代码有效:

import pandas as pd

columns = ['Name', 'Location', 'IP Address']

data = [
    ['Router', 'China', '10.10.10.1    10.10.10.2     10.10.10.3'],
    ['Switch', 'USA', '192.168.1.1   192.168.1.2     192.168.1.3']
]

#df = pd.read_csv(your_file_name)
df = pd.DataFrame(data, columns=columns)

def extract_ip_addresses(df_group):
    row = df_group.iloc[0]
    name = row['Name']
    location = row['Location']
    grouped_data = [[name, location, ip] for ip in row['IP Address'].split()]
    return pd.DataFrame(grouped_data, columns=columns)

df.groupby(['Name', 'Location'], group_keys=False).apply(extract_ip_addresses).reset_index(drop=True)

这会产生这个结果:

    Name    Location    IP Address
0   Router  China   10.10.10.1
1   Router  China   10.10.10.2
2   Router  China   10.10.10.3
3   Switch  USA     192.168.1.1
4   Switch  USA     192.168.1.2
5   Switch  USA     192.168.1.3

在您的情况下,您可以通过pd.read_csv(your_file_name) 读取初始数据。

这里有一些详细的例子:

更多详情请参考Pandas documentation

【讨论】:

  • 我从未使用过 pandas,而且我在这里的代码中使用了一个函数,所以我不太确定如果我使用 Pandas 我的迭代会如何。但是,我一定会试试这个。谢谢!
  • 您可以将自定义代码添加到提取函数中。但我确实明白,去 Pandas 是一个更大的步骤。对于您的情况,其他答案更简单、更合适。
【解决方案2】:

我假设这些字段确实由逗号分隔,没有空格填充,并且 IP 地址由多个空格分隔。然后这将起作用:

RE_SEPARATOR = re.compile(' +')
with open(path) as f:
    for row in csv.DictReader(f):
        addresses = RE_SEPARATOR.split(row["IP Address"])
        for address in addresses:
            print(row["Name"], row["Location"], address)

您必须调整 print 函数调用,以便它提供您需要的输出格式(根据您的描述,这并不完全清楚)。

如果您想删除重复的地址,请改用:

        addresses = set(RE_SEPARATOR.split(row["IP Address"]))

这不会保留保留顺序。在 Python 3.7(以及非官方的 3.6)中,您可以使用 dict 来保留排序:

        addresses = dict.fromkeys(RE_SEPARATOR.split(row["IP Address"]))

【讨论】:

  • 感谢您理解我的问题并给出答案,尽管问题似乎含糊不清。这工作得很好!
  • 如果有重复的 IP 地址并且我想跳过这些迭代,那么我应该这样做:for address in addresses: if address == addresses: continue print(row["Name"], row["Location"], address)
  • 我添加了一些关于抑制重复的内容。
  • 是的!我使用了addresses = dict.fromkeys(RE_SEPARATOR.split(row["IP Address"])),这确实删除了多余的 IP 地址。谢谢!如果无论位置或名称如何,我都必须删除多余的 IP 地址?
猜你喜欢
  • 1970-01-01
  • 2021-04-08
  • 2014-06-09
  • 1970-01-01
  • 2014-07-19
  • 2021-03-19
  • 2017-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多