Python:如何解析到位的地方?

时间:2017-09-11 23:16:04

标签: python python-2.7

没有任何包含多列的标题:

john, 1, orange, chicken
mary, 7, purple, hamburger
joey, 2, yellow, chicken

4 个答案:

答案 0 :(得分:2)

你不需要Sub FilterDifferences3() 'Filtering by differences Dim rng As Range Dim rngUnion As Range Dim varColNum As Variant Dim Lrow As Long With Sheets("Sheet1") '~~> Get last row of Col M (Need to use Match() as .End(xlUp).Row only finds the last visible row Set rng = .Range("M:M") With WorksheetFunction On Error Resume Next Lrow = 1 Lrow = .Max(Lrow, .Match(1E+306, rng, 1)) Lrow = .Max(Lrow, .Match("*", rng, -1)) On Error GoTo 0 End With '~~> Identify the range and use it With Range("A1:M" & Lrow) .EntireRow.Hidden = False '~~> Build up range of every Col Which has red font Set rngUnion = Range("A1:M1") For Each varColNum In Array(11, 12, 13) '~~> Identify the range in current Col Which has red font .AutoFilter Field:=varColNum, Criteria1:=RGB(192, 0, 0), Operator:=xlFilterFontColor On Error Resume Next Set rngUnion = Union(rngUnion, ActiveSheet.AutoFilter.Range.Offset(1, 0).SpecialCells(xlCellTypeVisible)) On Error GoTo 0 .AutoFilter ' Turns AutoFilter off and shows all rows Next varColNum '~~> Hide All except the Header row .Offset(1, 0).EntireRow.Hidden = True '~~> Unhide the rows which have red font rngUnion.EntireRow.Hidden = False End With 'Copying differences and putting them into a file .UsedRange.SpecialCells(xlCellTypeVisible).Select Selection.Copy End With End Sub Sub FilterDifferences3a() 'Filtering by differences Dim ws As Worksheet Dim aarng As Range Dim rng As Range Dim rngK As Range Dim rngL As Range Dim rngM As Range Dim Lrow As Long Set ws = Sheets("Sheet1") With ws '~~> Get last row of Col M (Need to use Match() as .End(xlUp).Row only finds the last visible row Set rng = .Range("M:M") With WorksheetFunction On Error Resume Next Lrow = 1 Lrow = .Max(Lrow, .Match(1E+306, rng, 1)) Lrow = .Max(Lrow, .Match("*", rng, -1)) On Error GoTo 0 End With '~~> Identify the range and use it With Range("A1:M" & Lrow) .EntireRow.Hidden = False '~~> Identify the range in Col K Which has red font .AutoFilter Field:=11, Criteria1:=RGB(192, 0, 0), Operator:=xlFilterFontColor On Error Resume Next Set rngK = ActiveSheet.AutoFilter.Range.Offset(1, 0).SpecialCells(xlCellTypeVisible) On Error GoTo 0 If rngK Is Nothing Then Set rngK = Range("A1:M1") .AutoFilter ' Turns AutoFilter off and shows all rows '~~> Identify the range in Col L Which has red font .AutoFilter Field:=12, Criteria1:=RGB(192, 0, 0), Operator:=xlFilterFontColor On Error Resume Next Set rngL = ActiveSheet.AutoFilter.Range.Offset(1, 0).SpecialCells(xlCellTypeVisible) On Error GoTo 0 If rngL Is Nothing Then Set rngL = Range("A1:M1") .AutoFilter ' Turns AutoFilter off and shows all rows '~~> Identify the range in Col M Which has red font .AutoFilter Field:=13, Criteria1:=RGB(192, 0, 0), Operator:=xlFilterFontColor On Error Resume Next Set rngM = ActiveSheet.AutoFilter.Range.Offset(1, 0).SpecialCells(xlCellTypeVisible) On Error GoTo 0 If rngM Is Nothing Then Set rngM = Range("A1:M1") .AutoFilter ' Turns AutoFilter off and shows all rows '~~> Hide All except the Header row .Offset(1, 0).EntireRow.Hidden = True '~~> Unhide the rows which have red font Union(rngK, rngL, rngM).EntireRow.Hidden = False End With 'Copying differences and putting them into a file .UsedRange.SpecialCells(xlCellTypeVisible).Select Selection.Copy End With End Sub ,只需要简单的python。这个解决方案在内存方面非常有效,因为它只是逐行操作。

csv

这比列表理解要高得多,这需要在内存中读取和存储将写入文件的所有数据。

<强>计时

with open('temp.csv', 'r') as fin, open('temp2.csv', 'w') as fout:
    for row in fin:
        if row.split()[3] == 'chicken':
            fout.write(row)

答案 1 :(得分:1)

您可以使用标准库中的csv

import csv

with open('old.csv') as old_file, open('new.csv', 'w') as new_file:
    cr = csv.reader(old_file)
    cw = csv.writer(new_file)
    cw.writerows([r for r in cr if r[3] == 'chicken'])

答案 2 :(得分:1)

import csv

with open('input.csv') as input_file, open('output.csv', 'w', newline='') as output_file:
    reader = csv.reader(input_file, delimiter=',')
    writer = csv.writer(output_file, delimiter=',')
    writer.writerows(filter(lambda x: x[3].strip() != 'chicken', reader))

首先,我正在使用上下文管理器来正确关闭文件。然后你有两个用于读写csv的对象。最后一行在第四列中重写了鸡,而没有将整个文件加载到内存中。

答案 3 :(得分:1)

虽然您可以使用Python module: csv来实例化您自己的阅读器,但是将每一行处理成一个元组,然后遍历元组以选择给定列符合您标准的所有项目......

...您还可以使用Pandas库更加简洁地完成此操作,该库是NumPy构建的,而SciPySQLite3生态系统的一部分。< / p>

对于这样一个简单的操作,似乎需要安装和导入很多代码。但这引出了一个问题:你是不是只是想做一些非常具体和小规模的事情?或者你在写一些可能需要扩展到更大的数据集并最终支持更复杂的分析或查询的东西?

学习Pandas和NumPy非常值得投资。安装它非常简单,然后您可以在处理数组,系列或&#34;框架中的数据时随时使用它。 (表格,标签和索引等电子表格)。

以下是你如何处理熊猫:

import pandas as pd
data_file = './mydata.csv'  ## <-- Change this to match yours
data = pd.read_csv(data_file)
rows = data[data.loc[:,3]=='chicken']
## Use rows here

Nota Bene:您必须确保您的CSV数据是&#34;清洁&#34;或者您已确保指定CSV文件中实际存在的值。例如,当我将您的示例数据剪切并粘贴到本地文件中时,我没有考虑您在逗号后面的前导空格。

当然你可以选择 ==&#39;鸡肉&#39; (请注意前导空格)作为匹配条件,或者您可以使用Pandas DataFrame .map()来选择数据:

...
data[data.loc[:,3].map(lambda x: 'chicken' in x)]

...这将匹配第3列(包含字符串&#39; chicken&#39;)的任何数据行。但是这种映射难以阅读,而且可能效率较低。

这些示例可能看起来有点难以阅读,特别是如果您正在阅读使用Pandas的其他示例。这是因为传统上正在处理标记的DataFrame。您可以通过简单地分配名称列表来轻松地将您自己的标签添加到内存中的数据中:

import pandas as pd
data_file = './mydata.csv'  ## <-- Change this to match yours
data = pd.read_csv(data_file)

# Add this:
data.columns=['name', 'num', 'color', 'food']
# Select with this:
rows = data[data['food']=='chicken']

......更具可读性。

将Pandas用于这样的事情的一个优点是它可以有效地处理相当大的数据集;数十,甚至数百,数千行应该在具有合理可用内存的现代系统上没有问题。

要处理索引表达式(数据[&#39; food&#39;] ==&#39; chicken&#39; )Pandas会生成一个&#34;广播&#的功能34;在整个数据结构中,产生一个布尔列表,然后用于选择所有匹配的行。必须将操作必须呈现为低级别的机器形式,这比在解释器中逐列逐行迭代数据更有效。

另一种完全不同的方法是读取CSV数据并将其编组到您自己的SQL数据库中。就像Python包含CSV模块一样,它在标准库中也包含一个完整的ufuncs子系统。

这似乎比在迭代数据时使用数据,或者使用Pandas或将数据读入DataFrame并使用其功能更为复杂。另一方面,它还允许您以更加强大和高效的形式保存数据。每次将CSV源中的数据插入或更新到SQLite数据库文件中时,都可以将这些数据重新用于各种查询和其他操作。

以下是一个例子:

import csv
import sqlite3

database = ':memory:'  ## <-- replace this is a filename to make the data persisten!
conn = sql.connect(':memory:')
db = conn.cursor()
results = db.execute('CREATE TABLE IF NOT EXISTS data (name VARCHAR, num INTEGER, color VARCHAR, food VARCHAR)')
## Could use data.to_sql('data', conn) if you've already created
## the data DataFrame as in the previous example

stmt_ins = 'INSERT INTO data (name, num, color, food) VALUES (?, ?, ?, ?)'
## Could use less robust: stmt_ins = "INSERT INTO data VALUES (?, ?, ?, ?)"

with open(data_file) as f:
    reader = csv.reader(f)
    for row in reader:
        if len(row) != 4:
            # Skip errors
            continue
        try:
            row[1] == int(row[1])
        except ValueError, err:
            # Skip errors
            continue
        results = None
        try:
            results = db.execute(stmt_ins, row)
        except sqlite3.Error:
            # Skip errors
            continue
        if results.rowcount != 1:
            # Ignore the error
            pass

rows = db.execute("SELECT * FROM data WHERE food = 'chicken'").fetchall()
# db.close(); conn.close()

你可能会在一开始就觉得有点吓人。 with 语句只是设置文件读取上下文;所以我们的文件将在退出后续的代码套件(块)时自动关闭。

在该上下文中,我们设置了一个简单的CSV阅读器,然后迭代每一行。这是使用CSV模块处理任何数据的框架。

在我们的循环中,我们只是跳过任何不完整的记录,尝试将第二个字段转换为整数,跳过失败的任何记录,尝试执行我们的SQL INSERT语句,跳过任何错误,并检查我们是否插入了一行(并忽略那里的任何错误)。

在24行代码中,几乎有一行代码可以跳过我们数据中的任何错误。我已将它们包含在此处,因此您知道如何以及在何处添加更多有用的错误报告或处理。

即使是从字符串到整数的显式转换对于SQLite3也是可选的(在这里给出我的数据库连接和模式)。但是,我在我的示例中展示了这项工作,因为在大多数情况下使用其他数据库甚至SQLite中的其他设置都是必要的。

如评论中所述,此代码将在内存中创建和操作数据表。只需用任意文件名替换:memory:即可将数据插入文件中;取消注释最后一个注释行,您将干净地保存数据库并关闭连接。

此代码示例中有许多细微的细微差别。这些是在初学者水平教程中经常被忽略的事物,并且必须在以后学习,通常来自错误和杂乱的现实世界数据集的痛苦经历。

&#34; IF NOT NOT EXISTS&#34;在我们的&#39;创建表&#39;&#39;命令允许此代码干净地工作,即使我们已经从先前的会话中保存了数据库文件中的数据,并且我们正在向其添加更多数据。 stmt_ins 会明确列出列,以便即使您已将其他列(例如自动递增主键)添加到表中,它也能正常工作。 (我建议健壮的代码总是为SQL SELECT,INSERT和UPDATE语句提供显式列指示符,以便您的代码可以继续使用各种数据库模式更改。)

此代码段可用作从任何CSV文件创建SQLite数据库的框架。当然,您可以使用常见的引用完整性约束(如PRIMARY KEY,NOT NULL和UNIQUE)以及外键REFERENCES创建更复杂的数据库模式,以及自动处理主键,组合键,触发器和自定义检查约束等等。您可以添加索引,当然,您生成的数据库可以有效地支持更复杂的查询和操作。

正如Pandas / NumPy可以将花哨的索引和其他操作解析为通过数组广播的低级代码(&#34; vectorized&#34;),SQLite3将使用它解析SQL查询和其他一些正确编码的语句&#39 ; s&#34;查询计划程序。&#34;正如一些阵列操作必须以适合NumPy&#34;广播&#34;的形式表达。 (经常使用.executemany()人经常需要制作SQL以与 .fetchmany(xxx) 方法一起使用。

使用SQLite3,如果使用数据文件,您将能够处理的数据集远远大于系统RAM(内存)中的数据集。此代码示例将处理任意大小的数据集的INSERT处理(创建数据库)(受磁盘空间限制)。但是如果&#34;鸡的数量和#34;如果行太大,您必须将对 .fetchall()的调用更改为SQLAlchemy上的循环...其中xxx是您在每次迭代时可以处理的行数

同样,这是介绍性教程未涉及的那种考虑因素,但是在您已经编写了符合这些类型的代码之后必须要学习这些内容很烦人。限制。

当然你也可以结合这些建议。如果您将CSV数据处理成SQL数据库,那么您可以使用* data = pd.read_sql(&#39; SELECT * FROM data&#39;,conn)*(其中&#34; conn&#34)将数据读入Pandas ;是与任何Python DBAPI兼容数据库或Apache PySpark&#34; selectable&#34;对象建立的连接,&#34; data&#34;是我们的视图表的名称)。 (正如其中一条评论中所述,您可以通过单个方法调用将数据从Pandas导出到SQL.Pandas将根据DataFrame的元数据为您创建合理的架构。(当然Pandas用于处理内存中的数据......对于更大的数据集,要么对文件中的数据进行批处理,要么查看IPython Parallel或其他方法,通过它可以在集群中为您分发Python计算({{3}}例子)。

我意识到我已超越你的要求了。但使用Python的一个方面是利用生态系统提供的工具。对您的问题的简单回答不会为您提供,也不会为搜索带来这些问题的其他人提供这些问题,以及发现该生态系统有多丰富和深层的方法。