[英]How to read a csv with unknown no of columns and compare it with another and retrieve values
[英]Compare 2 .CSV with unknown number of columns and names
並提前感謝任何建議。 這是第一次發布的海報,所以我會盡力提供所有必需的信息。 我也是Python的初學者,一直在做一些在線教程,以及StackOverflow的一些復制/粘貼編碼,它是FrankenCoding ......所以我可能接近這個錯誤...
我需要比較兩個CSV文件,這些文件的列數會有變化,只有2列匹配(例如,一個文件中的email_address,另一個文件中的EMAIL)。 這兩個文件都有標題,但這些標題的名稱可能會更改。 文件大小可能從幾千行到+2,000,000,可能有100多列(但更可能有一些)。
輸出到第三個'results.csv'文件,包含所有信息。 它可以是合並(所有唯一條目),減法(刪除一個或另一個中存在的條目)或交叉(兩者中都存在的所有條目)。
我在這里搜索過,發現了很多很好的信息,但是我看到的所有信息在文件中都有固定數量的列。 我嘗試過dict和dictreader,我知道答案就在那里,但是現在,我有點困惑。 但由於我幾天沒有取得任何進展,而且我只能在這方面投入太多時間,所以我希望能夠朝着正確的方向努力。
理想情況下,我想學習如何自己動手,這意味着要了解數據是如何“四處移動”的。
提取下面的CSV文件,我沒有添加更多列然后(我認為)必要,我現在擁有的數據集將匹配Originalid / UID或emailaddress / email,但情況可能並非總是如此。
Original.csv
"originalid","emailaddress",""
"12345678","Bob@mail.com",""
"23456789","NORMA@EMAIL.COM",""
"34567890","HENRY@some-mail.com",""
"45678901","Analisa@sports.com",""
"56789012","greta@mail.org",""
"67890123","STEVEN@EMAIL.ORG",""
Compare.CSV
"email","","DATEOFINVALIDATION_WITH_TIME","OPTOUTDATE_WITH_TIME","EMAIL_USERS"
"Bob@mail.com",,,"true"
"NORMA@EMAIL.COM",,,"true"
"HENRY@some-mail.com",,,"true"
"Henrietta@AWESOME.CA",,,"true"
"NORMAN@sports.CA",,,"true"
"albertina@justemail.CA",,,"true"
results.csv中的數據應該是Original.CSV + Compare.csv中所有列的所有列,但不是匹配的列(電子郵件):
"originalid","emailaddress","","DATEOFINVALIDATION_WITH_TIME","OPTOUTDATE_WITH_TIME","EMAIL_USERS"
"12345678","Bob@mail.com","",,,"true"
"23456789","NORMA@EMAIL.COM","",,,"true"
"34567890","HENRY@some-mail.com","",,,"true"
以下是我現在的結果:
email,,DATEOFINVALIDATION_WITH_TIME,OPTOUTDATE_WITH_TIME,EMAIL_USERS
Bob@mail.com,,,true,"['12345678', 'Bob@mail.com', '']"
NORMA@EMAIL.COM,,,true,"['23456789', 'NORMA@EMAIL.COM', '']"
HENRY@some-mail.com,,,true,"['34567890', 'HENRY@some-mail.com', '']"
這就是我在使用代碼的地方,print語句將文件中的匹配數據返回到屏幕而不是文件,所以我在那里缺少一些東西。
*****我沒有從original.csv文件中獲取標題,數據正在進入。
import csv
def get_column_from_file(filename, column_name):
f = open(filename, 'r')
reader = csv.reader(f)
headers = next(reader, None)
i = 0
max = (len(headers))
while i < max:
if headers[i] == column_name:
column_header = i
# print(headers[i])
i = i + 1
return(column_header)
file_to_check = "Original.csv"
file_console = "Compare.csv"
column_to_read = get_column_from_file(file_console, 'email')
column_to_compare = get_column_from_file(file_to_check, 'emailaddress')
with open(file_console, 'r') as master:
master_indices = dict((r[1], r) for i, r in enumerate(csv.reader(master)))
with open('Compare.csv', 'r') as hosts:
with open('results.csv', 'w', newline='') as results:
reader = csv.reader(hosts)
writer = csv.writer(results)
writer.writerow(next(reader, []))
for row in reader:
index = master_indices.get(row[0])
if index is not None:
print (row +[master_indices.get(row[0])])
writer.writerow(row +[master_indices.get(row[0])])
謝謝你的時間!
拍
現在看起來你只使用一次編寫器作為標題:
writer.writerow(next(reader, []))
弗朗西斯科指出,取消注釋最后一行可能會解決您的問題。 您可以通過刪除行開頭的“#”來完成此操作。
我喜歡你自己想要這樣做,並認識到需要“理解數據是如何移動的”。 這正是你應該如何思考這個問題:專注於數據的移動而不是結果。 有些人可能不同意我,但我認為這是一個很好的理念,因為它將使未來的重用更容易。
您沒有嘗試構建一個組合了兩個CSV的工具,您嘗試根據公共參考(電子郵件地址)組織數據(恰好來自CSV)並將結果輸出為CSV。 因為您正在討論潛在的大型數據集(+2,000,000 [行],可能有100多列),所以認識到注意漸近運行時非常重要。 如果您不知道這是什么,我建議您閱讀Big-O表示法和漸近算法分析。 沒有這個你可能沒問題。
首先,您要確定每個CSV中的哪個是您的密鑰。 你已經在'Original.csv'中為'Compare.csv'和'emailaddress'做了'email'。 現在,自己構建一個函數,根據密鑰從CSV生成字典。
def get_dict_from_csv(path_to_csv, key):
with open(path_to_csv, 'r') as f:
reader = csv.reader(f)
headers, *rest = reader # requires python3
key_index = headers.index(key) # find index of key
# dictionary comprehensions are your friend, just think about what you want the dict to look like
d = {row[key_index]: row[:key_index] + row[key_index+1:] # +1 to skip the email entry
for row in rest}
headers.remove(key)
d['HEADERS'] = headers # add headers so you know what the information in the dict is
return d
現在,您可以在兩個CSV上調用此功能。
file_console_dict = get_dict_from_csv('Compare.csv', 'email')
file_to_check_dict = get_dict_from_csv('Original.csv', 'emailaddress')
現在你有兩個關鍵字相同的信息。 現在我們需要一個函數將它們組合成一個字典。
def combine_dicts(*dicts):
d, *rest = dicts # requires python3
# iteratively pull other dicts into the first one, d
for r in rest:
original_headers = d['HEADERS'][:]
new_headers = r['HEADERS'][:]
# copy headers
d['HEADERS'].extend(new_headers)
# find missing keys
s = set(d.keys()) - set(r.keys()) # keys present in d but not in r
for k in s:
d[k].extend(['', ] * len(new_headers))
del r['HEADERS'] # we don't want to copy this a second time in the loop below
for k, v in r.items():
# use setdefault in case the key didn't exist in the first dict
d.setdefault(k, ['', ] * len(original_headers)).extend(v)
return d
現在你有一個dict,它包含你想要的所有信息,你需要做的就是將它寫回CSV。
def write_dict_to_csv(output_file, d, include_key=False):
with open(output_file, 'w', newline='') as results:
writer = csv.writer(results)
# email isn't in your HEADERS, so you'll need to add it
if include_key:
headers = ['email',] + d['HEADERS']
else:
headers = d['HEADERS']
writer.writerow(headers)
# now remove it from the dict so we can iterate over it without including it twice
del d['HEADERS']
for k, v in d.items():
if include_key:
row = [k,] + v
else:
row = v
writer.writerow(row)
這應該是它。 打電話給所有這些只是
file_console_dict = get_dict_from_csv('Compare.csv', 'email')
file_to_check_dict = get_dict_from_csv('Original.csv', 'emailaddress')
results_dict = combine_dicts(file_to_check_dict, file_console_dict)
write_dict_to_csv('results.csv', results_dict)
你可以很容易地看到它如何擴展到任意多個詞典。
您說您不希望電子郵件出現在最終的CSV中。 這對我來說是違反直覺的,所以我在write_dict_to_csv()中做了一個選項,以防你改變主意。
當我運行以上所有內容時,我得到了
email,originalid,,,DATEOFINVALIDATION_WITH_TIME,OPTOUTDATE_WITH_TIME,EMAIL_USERS
Bob@mail.com,12345678,,,,true
NORMA@EMAIL.COM,23456789,,,,true
HENRY@some-mail.com,34567890,,,,true
Analisa@sports.com,45678901,,,,,
greta@mail.org,56789012,,,,,
STEVEN@EMAIL.ORG,67890123,,,,,
Henrietta@AWESOME.CA,,,,,true
NORMAN@sports.CA,,,,,true
albertina@justemail.CA,,,,,true
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.