【问题标题】:Dropping first row of CSV if condition如果有条件,则删除 CSV 的第一行
【发布时间】:2020-06-15 16:45:51
【问题描述】:

我正在构建一个应用程序,其中一部分是下载 GCP 存储中存在的 csv 文件。

我使用这个函数来获取csv,注意,它是作为字符串下载的。

def get_my_csv(run, library):
    storage_client = storage.Client()
    bucket = storage_client.get_bucket(BUCKET_NAME)
    blobs = bucket.list_blobs(prefix="{}/{}".format(run, library))
    for blob in blobs:
        return blob.download_as_string().decode("utf-8")

获得 CSV 后,我将其解析为 pandas 数据框,如下所示:

csv_to_use = get_my_csv(run, library)
reader = csv.DictReader(csv_to_use.splitlines())
rows = [r for r in reader]
df = pd.DataFrame(rows)

现在我遇到的问题是负责上传此 CSV 文件的人员有时会搞砸,我得到的 CSV 文件如下所示:

Analysis pipeline:,Class II - DPB Full Length,,,,
Local ID,Sample ID,For Code ,For Code Seq,Rev Code Name,Rev Code Seq
4,2949,004F,GGTAGTGTGTATCAGTACATG,004R,GGTAGTGTGTATCAGTACATG
5,1596,005F,GGTAGACACGCATGACACACT,005R,GGTAGACACGCATGACACACT
13,3319,013F,GGTAGACACTGACGTCGCGAC,013R,GGTAGACACTGACGTCGCGAC

您可能会注意到,在实际的头文件之前有一行。我该如何处理?此外,我永远不确定他们实际上可能会在标题中放入什么。有没有办法让我的代码足够聪明来处理这个问题?

如果不够聪明,我可以使用什么逻辑来删除此行:Analysis pipeline:,Class II - DPB Full Length,,,, 并将Local ID,Sample ID,For Code ,For Code Seq,Rev Code Name,Rev Code Seq 作为我的标题?

更新

基本上,For Code ,For Code Seq,Rev Code Name,Rev Code Seq 应该始终出现在标题中。我怎样才能跳过直到找到这个,把它作为标题并解析其余部分?

【问题讨论】:

  • 第一列标签是否总是“本地 ID”?您可以检查它是否在行的开头,如果不是,则丢弃它并检查下一行。否则最好先找到带数字的行,然后从前一行开始。
  • 是的。实际标题的第一行应始终为“本地 ID”。如何在找到“本地 ID”之前跳过?
  • 在将其读入熊猫之前,不需要的行的字符串输入是否还包含正确数量的列作为 csv (,,,,)。或者它只是一些字符串?很高兴获得原始输入示例可以是get_my_csv(run, library) return 的片段。
  • @DominicD 可以是“本地 ID”或“代码 UID”。这不是很有帮助。但标题应始终包含 For Code ,For Code Seq,Rev Code Name,Rev Code Seq 我如何查找此标题并将其设为标题?
  • @A.Bergen 我粘贴的是原始 CSV。它确实包括 (,,,,)

标签: python pandas numpy csv


【解决方案1】:

这是检查您所说的内容应始终位于列标题中的基本方法。

csv_to_use = get_my_csv(run, library)
i = 0
for i, row in enumerate(csv_to_use.splitlines()):
    row_split = row.split(',')
    broken = False
    for j,label in enumerate(row_split):
        if 'For Code' in label and 'For Code Seq' in row_split[j+1] and 'Rev Code Name' in row_split[j+2] and 'Rev Code Seq' in row_split[j+3]:
            broken = True
            break
    if broken:
        break
reader = csv.DictReader(csv_to_use.splitlines()[i:])
rows = [r for r in reader]

【讨论】:

  • 所以 rows 是 <class 'collections.OrderedDict'> - 另一个问题是标题中可能有空格。所以"For Code" 可能是" For Code""For Code "" For Code "
  • 感谢多米尼克的努力! Serge 的回答效果很好!
  • 不用担心。我已经对其进行了编辑以考虑空格并检查所有标签。但是搜索第一行数字似乎是一种更简单的方法。
  • AttributeError: 'collections.OrderedDict' object has no attribute 'split' rows 是 OrderedDict 而不是 String
  • 很抱歉。检查原始字符串然后才调用 CSV Reader 更有意义。我已经修复了这个答案以供任何人将来参考。
【解决方案2】:

我会假设第一个数据行的第一个字段是数字,而实际的标题只是前一个。

我愿意:

import io
import re
...

numeric = re.compile(r'\d+$')                 # a regex to match a numeric field
csv_to_use = get_my_csv(run, library)
reader = csv.reader(io.StringIO(csv_to_use))
rows = list(reader)

# search first data row:
for i, row in enumerate(rows):
    if numeric.match(row[0]):
        break
if i == 0: i=1                    # ensure at least a header row...

# build the dataframe
df = df.DataFrame(rows[i:], columns=rows[i-1])

如果要过滤标题中的任何空白,只需将最后一行替换为:

df = df.DataFrame(rows[i:], columns=[r.replace(' ', '') for r in rows[i-1]])

【讨论】:

  • 太棒了!这是完美的!
  • 有没有办法处理标题中的空格?
  • @DuDoff:可能。你想对他们做什么?去掉开头和结尾的空格,或删除(或用非空白字符替换)标题字段中的任何空格?
  • 删除所有空格。
  • LocalID SampleID ForBarcodeName ForBarcodeSequence RevBarcodeName RevBarcodeSequence 删除所有空格。
猜你喜欢
  • 2015-10-13
  • 2013-08-09
  • 1970-01-01
  • 1970-01-01
  • 2021-06-06
  • 2012-06-28
  • 2022-06-28
  • 2015-03-11
  • 2017-09-27
相关资源
最近更新 更多