从大型csv文件中提取行时数据丢失

tktrz96b  于 2022-12-06  发布在  其他
关注(0)|答案(3)|浏览(209)

这是我上一个问题的延续。我有两个文件,file1.csv和一个名为master_file.csv的大csv。它们有几个列,有一个共同的列名EMP_Code
文件1示例:
| EMP_名称|EMP_代码|EMP_部门|
| - -|- -|- -|
| B| f367系列|abc公司|
| 一种|c264基因|某某|
| C语言|264天|abc公司|
master_file示例:

EMP_name EMP_age EMP_Service EMP_Code EMP_dept
a         30       6           c264     xyz
b         29       3           f367     abc
r         27       1           g364     lmn
d         45       10          c264     abc
t         50       25          t453     lmn

我想使用file1中的所有EMP_Code值从master_file中提取类似的行。我尝试了下面的代码,但丢失了很多数据。我无法读取完整的主csv文件,因为它大约有20 GB。有数百万行,内存不足。我想以块的形式读取master_file,并提取file1中每个EMP_Code的完整行,然后将其保存到新文件Employee_full_data中。

import csv
import pandas as pd

df = pd.read_csv(r"master_file.csv")
li = [c264,f367]
full_data = df[df.EMP_Code.isin(li)]
full_data.to_csv(r"Employee_full_data.csv", index=False)

我也尝试了下面的代码。每当我使用EMP_Code列时,我收到一个空文件,当我使用Emp_nameEMP_dept这样的列时,我可以正常工作。我想使用EMP_Code提取数据。

import csv
import pandas as pd

df = pd.read_csv(r"file1.csv")

list_codes = list(df.EMP_Code)
selected_rows = []
with open(r"master_file.csv") as csv_file:
    reader = csv.DictReader(csv_file)
    for row in reader:
        if row['EMP_Code'] in list_codes:
            selected_rows.append(row)`

article_usage = pd.DataFrame.from_records(selected_rows)
article_usage.to_csv(r"Employee_full_data.csv", index=False)

有没有其他方法可以提取数据而不丢失数据?我听说过连接和阅读数据块,但不知道如何在这里使用它。任何帮助都是感谢

vshtjzan

vshtjzan1#

我在你的小例子上运行了你的第二个例子中的代码(使用csv.DictReader),它成功了。我猜你的问题可能与你提到的master_file的实际规模有关。
问题可能是,尽管使用了csv.DictReader来输入信息,但在写出之前,您仍然使用Pandas Dataframe 来聚合所有内容,并且输出可能超出了您的内存预算。
如果这是真的,那么使用csv.DictWriter流输出。唯一棘手的是设置写入器,因为它需要知道字段名,而字段名在读取第一行之前是不知道的,所以我们将在读取循环的第一次迭代中设置写入器。
(我已经删除了with open(...上下文,因为我认为它们增加了太多的缩进)

df = pd.read_csv(r"file1.csv")
list_codes = list(df.EMP_Code)

f_in = open(r"master_file.csv", newline="")
reader = csv.DictReader(f_in)

f_out = open(r"output.csv", "w", newline="")

init_writer = True
for row in reader:
    if init_writer:
        writer = csv.DictWriter(f_out, fieldnames=row)
        writer.writeheader()
        init_writer = False

    if row["EMP_Code"] in list_codes:
        writer.writerow(row)

f_out.close()
f_in.close()

| EMP_名称|EMP年龄(_A)|EMP_服务|EMP_代码|EMP_部门|
| - -|- -|- -|- -|- -|
| 一种|三十|六个|c264基因|某某|
| B|二十九人|三个|f367系列|abc公司|
| 日|四十五|10个|c264基因|abc公司|
如果你想完全摆脱Pandas:

list_codes = set()
with open(r"file1.csv", newline="") as f:
    reader = csv.DictReader(f)
    for row in reader:
        list_codes.add(row["EMP_Code"])
7kjnsjlb

7kjnsjlb2#

您只需将chunksize=<SOME INTEGER>传递给panda的.read_csv函数(请参阅此处的文档)
如果你传递一个chunksize=2,你将把文件读入2行的 Dataframe 。或者......更准确地说,它将把csv的2行读入一个 Dataframe 。然后你可以把你的过滤器应用到这个2行的 Dataframe 上,并把它“累积”到另一个 Dataframe 中。下一次迭代将读取接下来的两行,你可以随后过滤......泡沫,冲洗和重复:

import pandas as pd
li = ['c264', 'f367']

result_df = pd.DataFrame()
with pd.read_csv("master_file.csv", chunksize=2) as reader:
    for chunk_df in reader:
        filtered_df = chunk_df[chunk_df.EMP_Code.isin(li)]
        result_df = pd.concat([result_df, filtered_df])
print(result_df)

# Outputs:
#   EMP_name  EMP_age  EMP_Service EMP_Code EMP_dept
# 0        a       30            6     c264      xyz
# 1        b       29            3     f367      abc
# 3        d       45           10     c264      abc
3qpi33ja

3qpi33ja3#

修复这些类型的文件读/写任务的一种方法是使用生成器,并以可以处理的块或部分(内存或其他约束)读取所需的数据。

def read_line():
    with open('master_file.csv','r') as fid:
        while (line:= fid.readline().split()):
            yield line

这个简单生成器在每个调用中都会给予一个新的行。2现在你可以简单地迭代这个行来做你感兴趣的过滤,并建立你的新 Dataframe 。

r_line = read_line()    
for l in r_line:
    print(l)

您可以修改生成器,例如解析并返回列表或多行等。

相关问题