diff --git a/python-csv/README.md b/python-csv/README.md new file mode 100644 index 0000000000..8a1947cf92 --- /dev/null +++ b/python-csv/README.md @@ -0,0 +1,44 @@ +# Reading and Writing CSV Files in Python + +This folder provides the code examples for the Real Python tutorial [Reading and Writing CSV Files in Python](https://realpython.com/python-csv/). + +Consider creating a [Python virtual environment](https://realpython.com/python-virtual-environments-a-primer/) before installing the dependencies: + +```shell +$ python3 -m venv .venv/ --prompt python-csv +$ source .venv/bin/activate +(python-csv) $ python -m pip install -r requirements.txt +``` + +The scripts read their data files from the current working directory, so run them from inside this folder: + +```shell +(python-csv) $ python read_csv_with_reader.py +``` + +Each script holds the code from one section of the tutorial: + +| File | Tutorial section | +| --- | --- | +| `read_csv_with_reader.py` | Reading CSV Files With `csv` | +| `read_csv_into_dictionary.py` | Reading CSV Files Into a Dictionary With `csv` | +| `write_csv_with_writer.py` | Writing CSV Files With `csv` | +| `write_csv_from_dictionary.py` | Writing CSV File From a Dictionary With `csv` | +| `read_csv_with_pandas.py` | Reading CSV Files With `pandas` | +| `write_csv_with_pandas.py` | Writing CSV Files With `pandas` | + +The examples that the tutorial shows at the interactive prompt are included in +`read_csv_with_pandas.py` as `print()` calls, in the same order as the article, +so that you can run the whole section as a single script. + +There are also three data files used throughout the tutorial: + +| File | Description | +| --- | --- | +| `employee_birthday.csv` | Employee names, departments, and birthday months read by the `csv` examples. | +| `employee_addresses.csv` | Addresses containing an embedded comma, used to illustrate the optional `reader` parameters. | +| `hrdata.csv` | Employee hire dates, salaries, and sick days read by the `pandas` examples. | + +Running the writing examples creates `employee_file.csv`, `employee_file2.csv`, +and `hrdata_modified.csv` in this folder. Those files aren't checked in, since +the tutorial generates them. diff --git a/python-csv/employee_addresses.csv b/python-csv/employee_addresses.csv new file mode 100644 index 0000000000..fa1ceb4aa3 --- /dev/null +++ b/python-csv/employee_addresses.csv @@ -0,0 +1,3 @@ +name,address,date joined +john smith,1132 Anywhere Lane Hoboken NJ, 07030,Jan 4 +erica meyers,1234 Smith Lane Hoboken NJ, 07030,March 2 diff --git a/python-csv/employee_birthday.csv b/python-csv/employee_birthday.csv new file mode 100644 index 0000000000..3918ab6c16 --- /dev/null +++ b/python-csv/employee_birthday.csv @@ -0,0 +1,3 @@ +name,department,birthday month +John Smith,Accounting,November +Erica Meyers,IT,March diff --git a/python-csv/hrdata.csv b/python-csv/hrdata.csv new file mode 100644 index 0000000000..ef0761b974 --- /dev/null +++ b/python-csv/hrdata.csv @@ -0,0 +1,7 @@ +Name,Hire Date,Salary,Sick Days remaining +Graham Chapman,03/15/14,50000.00,10 +John Cleese,06/01/15,65000.00,8 +Eric Idle,05/12/14,45000.00,10 +Terry Jones,11/01/13,70000.00,3 +Terry Gilliam,08/12/14,48000.00,7 +Michael Palin,05/23/13,66000.00,8 diff --git a/python-csv/read_csv_into_dictionary.py b/python-csv/read_csv_into_dictionary.py new file mode 100644 index 0000000000..5dde515cc4 --- /dev/null +++ b/python-csv/read_csv_into_dictionary.py @@ -0,0 +1,15 @@ +import csv + +with open("employee_birthday.csv", mode="r") as csv_file: + csv_reader = csv.DictReader(csv_file) + line_count = 0 + for row in csv_reader: + if line_count == 0: + print(f"Column names are {', '.join(row)}") + line_count += 1 + print( + f"\t{row['name']} works in the {row['department']} " + f"department, and was born in {row['birthday month']}." + ) + line_count += 1 + print(f"Processed {line_count} lines.") diff --git a/python-csv/read_csv_with_pandas.py b/python-csv/read_csv_with_pandas.py new file mode 100644 index 0000000000..1878daff73 --- /dev/null +++ b/python-csv/read_csv_with_pandas.py @@ -0,0 +1,29 @@ +import pandas + +df = pandas.read_csv("hrdata.csv") +print(df) + +print(type(df["Hire Date"][0])) + +df = pandas.read_csv("hrdata.csv", index_col="Name") +print(df) + +df = pandas.read_csv( + "hrdata.csv", + index_col="Name", + parse_dates=["Hire Date"], + date_format="%m/%d/%y", +) +print(df) + +print(type(df["Hire Date"].iloc[0])) + +df = pandas.read_csv( + "hrdata.csv", + index_col="Employee", + parse_dates=["Hired"], + date_format="%m/%d/%y", + header=0, + names=["Employee", "Hired", "Salary", "Sick Days"], +) +print(df) diff --git a/python-csv/read_csv_with_reader.py b/python-csv/read_csv_with_reader.py new file mode 100644 index 0000000000..59bbaf0954 --- /dev/null +++ b/python-csv/read_csv_with_reader.py @@ -0,0 +1,15 @@ +import csv + +with open("employee_birthday.csv") as csv_file: + csv_reader = csv.reader(csv_file, delimiter=",") + line_count = 0 + for row in csv_reader: + if line_count == 0: + print(f"Column names are {', '.join(row)}") + line_count += 1 + else: + print( + f"\t{row[0]} works in the {row[1]} department, and was born in {row[2]}." + ) + line_count += 1 + print(f"Processed {line_count} lines.") diff --git a/python-csv/requirements.txt b/python-csv/requirements.txt new file mode 100644 index 0000000000..f2918d21c9 --- /dev/null +++ b/python-csv/requirements.txt @@ -0,0 +1 @@ +pandas==3.0.5 diff --git a/python-csv/write_csv_from_dictionary.py b/python-csv/write_csv_from_dictionary.py new file mode 100644 index 0000000000..f1d231951b --- /dev/null +++ b/python-csv/write_csv_from_dictionary.py @@ -0,0 +1,17 @@ +import csv + +with open("employee_file2.csv", mode="w", newline="") as csv_file: + fieldnames = ["emp_name", "dept", "birth_month"] + writer = csv.DictWriter(csv_file, fieldnames=fieldnames) + + writer.writeheader() + writer.writerow( + { + "emp_name": "John Smith", + "dept": "Accounting", + "birth_month": "November", + } + ) + writer.writerow( + {"emp_name": "Erica Meyers", "dept": "IT", "birth_month": "March"} + ) diff --git a/python-csv/write_csv_with_pandas.py b/python-csv/write_csv_with_pandas.py new file mode 100644 index 0000000000..a56855e649 --- /dev/null +++ b/python-csv/write_csv_with_pandas.py @@ -0,0 +1,11 @@ +import pandas + +df = pandas.read_csv( + "hrdata.csv", + index_col="Employee", + parse_dates=["Hired"], + date_format="%m/%d/%y", + header=0, + names=["Employee", "Hired", "Salary", "Sick Days"], +) +df.to_csv("hrdata_modified.csv") diff --git a/python-csv/write_csv_with_writer.py b/python-csv/write_csv_with_writer.py new file mode 100644 index 0000000000..59380e01ef --- /dev/null +++ b/python-csv/write_csv_with_writer.py @@ -0,0 +1,9 @@ +import csv + +with open("employee_file.csv", mode="w", newline="") as employee_file: + employee_writer = csv.writer( + employee_file, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL + ) + + employee_writer.writerow(["John Smith", "Accounting", "November"]) + employee_writer.writerow(["Erica Meyers", "IT", "March"])