我有两个csv文件。 train_all.csv:
msno is_churn
0 waLDQMmcOu2jLDaV1ddDkgCrB/jl6sD66Xzs0Vqax1Y= 1
1 QA7uiXy8vIbUSPOkCf9RwQ3FsT8jVq2OxDr8zqa7bRQ= 1
2 fGwBva6hikQmTJzrbz/2Ezjm5Cth5jZUNvXigKK2AFA= 1
3 mT5V8rEpa+8wuqi6x0DoVd3H5icMKkE9Prt49UlmK+4= 1
4 XaPhtGLk/5UvvOYHcONTwsnH97P4eGECeq+BARGItRw= 1
5 GBy8qSz16X5iYWD+3CMxv/Hm6OPSrXBYtmbnlRtknW0= 1
6 lYLh7TdkWpIoQs3i3o6mIjLH8/IEgMWP9r7OpsLX0Vo= 1
它有1963891条记录,但只有1082190条唯一记录。这就是为什么我用pandas排序独特的msno-s。
其他csv约为30GB,用户日志包含超过9亿条记录。
msno date num_25 num_50 num_75 num_985 num_100 num_unq total_secs
rxIP2f2aN0rYNp+toI0Obt/N/FYQX8hcO1fTmmy2h34= 20150513 0 0 0 0 1 1 280.335
rxIP2f2aN0rYNp+toI0Obt/N/FYQX8hcO1fTmmy2h34= 20150709 9 1 0 0 7 11 1658.948
yxiEWwE9VR5utpUecLxVdQ5B7NysUPfrNtGINaM2zA8= 20150105 3 3 0 0 68 36 17364.956
yxiEWwE9VR5utpUecLxVdQ5B7NysUPfrNtGINaM2zA8= 20150306 1 0 1 1 97 27 24667.317
yxiEWwE9VR5utpUecLxVdQ5B7NysUPfrNtGINaM2zA8= 20150501 3 0 0 0 38 38 9649.029
我想遍历train_all.csv中的唯一msno-s,并在user_logs.csv中为每个msno搜索5个user_log记录。我的代码在大约20分钟后停止,在results.csv中只有104条记录 - 所需的输出文件匹配msno - user_logs。
import pandas as pd
import csv
reader = csv.reader(open('user_logs/user_logs.csv','r'))
writer = csv.writer(open('results.csv','w',newline=''))
data = pd.read_csv("train_all.csv")
unique_msnos = data["msno"].unique()
i = 0
for msno in range(len(unique_msnos)):
counter = 0
for row in reader:
results_row = row
if unique_msnos[msno] == row[0]:
writer.writerow(results_row)
counter+=1
if counter == 5:
i+=1
break
else:
continue
else:
continue
答案 0 :(得分:0)
可能的原因导致它在没有找到所有内容的情况下停止:
file.tell()
)来验证这一点(记住ctrl-c以打破它。)你可以通过在内部循环完成后(无论是通过StopIteration还是中断)将文件发送回开头来修复,以便内部循环可以搜索整个文件以查找msno。做好准备等待更长时间。
with open('user_logs/user_logs.csv','r') as infile:
reader = csv.reader(infile)
for msno in range(len(unique_msnos)):
counter = 0
#print(infile.tell())
for row in reader:
#inner_loop_stuff...
#inner_loop_stuff...
#inner_loop_stuff...
infile.seek(0)
unique_msnos
有1.1E6记录,reader
有9E8记录。对于unique_msnos
中的每条记录,您将迭代9e8次 - 这将是1e15-ish迭代。你必须小心嵌套循环。
当你checking for membership时,你应该使用一套。
unique_msnos = set(unique_msnos)
您想要跟踪找到的记录数量,这样可能会使unique_msnos
字典的值保持计数。
unique_msnos = dict.fromkeys(unique_msnos, 0)
然后迭代reader
检查成员身份并添加逻辑以查看是否已有5:
for row in reader:
c = unique_msnos.get(row[0], None)
if c in (5, None):
continue
writer.write(row)
unique_msnos[row[0]] += 1
...
这应该有所缓解 - 9e8次迭代。可能还有其他一些优化。
如果msno-s保证全部长度相同,则可以使用切片而不是使用csv.Reader来获得增量改进。我真的不知道csv读者有多快,但切片速度非常快。
像
这样的东西# unique_msnos is a dictionary
with open(open('user_logs/user_logs.csv','r') as f:
for line in f:
c = unique_msnos.get(line[:44], None)
....
它不会减少迭代次数,但如果你得到(a_small_improvement * 9e8)改进,那么它可能会很明显。
看起来你正在制作一个DataFrame然后扔掉它。直接从文件中生成unique_msnos
可能更快:
unique_msnos = {}
with open("train_all.csv") as f:
for line in f:
_, msno, churn = line.split()
unique_msnos[msno] = 0
您需要尝试检查它是否更快。
当您尝试使其工作并进行优化时,您可能希望自己制作一些较小的文件。只需为每个文件执行一次,然后使用小文件进行debuging。使用cprofile或timeit尝试找出瓶颈所在的位置
limit = 10000 # or whatever
with open(file_path, 'r') as infile, open(small_filepath, 'w') as outfile:
for n, line in enumerate(infile):
outfile.write(line)
if n == limit:
break