1 00:00:00,000 --> 00:00:02,940 [MUSIC PLAYING] 2 00:00:02,940 --> 00:00:05,192 3 00:00:05,192 --> 00:00:07,400 SPEAKER: Well, hello, one and all, and welcome to our 4 00:00:07,400 --> 00:00:10,350 short on Reading and Writing CSVs. 5 00:00:10,350 --> 00:00:15,530 Now, CSVs are great for storing data, in terms of comma-separated values, 6 00:00:15,530 --> 00:00:19,880 and they're great for analyzing data, particularly when coupled with Python. 7 00:00:19,880 --> 00:00:24,710 So I have here a program called views.py, which is not implemented yet, 8 00:00:24,710 --> 00:00:26,310 but will be soon. 9 00:00:26,310 --> 00:00:31,220 The goal of it is to read in some data from views.csv, 10 00:00:31,220 --> 00:00:34,380 these comma-separated values in this file here. 11 00:00:34,380 --> 00:00:40,010 And notice how I have, in this case, the names of each of the 36 views of Mount 12 00:00:40,010 --> 00:00:44,540 Fuji, some prints produced by the artist, Hokusai, in the 1830s. 13 00:00:44,540 --> 00:00:48,030 Now, I have here three columns of data, if you will. 14 00:00:48,030 --> 00:00:52,190 One called id, which identifies the id of the print. 15 00:00:52,190 --> 00:00:56,240 One called English title, which is the English title of the print. 16 00:00:56,240 --> 00:01:00,200 And one called Japanese title, which is the Japanese title of the print, 17 00:01:00,200 --> 00:01:01,050 as well. 18 00:01:01,050 --> 00:01:07,140 So notice here, if I go to 1.jpeg 2, I actually have a picture of the Great 19 00:01:07,140 --> 00:01:10,770 Wave off Kanagawa right here, as well. 20 00:01:10,770 --> 00:01:15,700 If I go to 2.jpeg, I'll see Fine Wind, Clear Morning. 21 00:01:15,700 --> 00:01:20,130 So there's actually a correspondence between the id's of the pictures here 22 00:01:20,130 --> 00:01:24,570 and the actual pictures, the dot jpegs I have stored in my code space here, 23 00:01:24,570 --> 00:01:25,470 as well. 24 00:01:25,470 --> 00:01:27,120 So I'll go ahead and close these. 25 00:01:27,120 --> 00:01:33,140 And our goal is to read in this CSV of views, and do a bit of image analysis 26 00:01:33,140 --> 00:01:33,640 on them. 27 00:01:33,640 --> 00:01:37,020 I think it'll be interesting if you actually find out how bright or not 28 00:01:37,020 --> 00:01:39,220 bright each of these photos is. 29 00:01:39,220 --> 00:01:41,880 In fact, we have a function here called, calculate 30 00:01:41,880 --> 00:01:48,380 brightness, which takes as input a file name, and returns to us 0 to 1 on a 0 31 00:01:48,380 --> 00:01:52,650 to 1 scale, how bright or not bright, how dark the image is. 32 00:01:52,650 --> 00:01:58,140 1 being brightest, completely white, and 0 being the darkest, completely black, 33 00:01:58,140 --> 00:01:59,370 in this case. 34 00:01:59,370 --> 00:02:02,940 So let's see if we can maybe start off by just reading whatever 35 00:02:02,940 --> 00:02:08,500 is inside of this CSV file and focus on the analyzing just a little bit later. 36 00:02:08,500 --> 00:02:12,840 So our first step will be to try to open this CSV file 37 00:02:12,840 --> 00:02:15,930 and maybe get a sense for the data that's inside of it, 38 00:02:15,930 --> 00:02:19,560 and make sure we can actually see that data in Python, too. 39 00:02:19,560 --> 00:02:25,090 So to read a CSV file, we've seen we should use the CSV library. 40 00:02:25,090 --> 00:02:27,330 I'll import CSV up top. 41 00:02:27,330 --> 00:02:30,390 And it turns out, that we've also seen CSV, 42 00:02:30,390 --> 00:02:38,250 the library comes with a object called a DictReader, which 43 00:02:38,250 --> 00:02:44,100 actually allows us to take a file and read each row of it as a dictionary. 44 00:02:44,100 --> 00:02:47,080 But before we can get there, we need to open our file first. 45 00:02:47,080 --> 00:02:51,480 And we've seen too to do that, we can use a keyword called, with, 46 00:02:51,480 --> 00:02:56,160 which takes care of opening and closing our file automatically 47 00:02:56,160 --> 00:02:58,690 for us, thanks to the magic of Python. 48 00:02:58,690 --> 00:03:03,240 So I can type, with open, and then give the name 49 00:03:03,240 --> 00:03:08,310 of the file I'm hoping to open, in this case, views.csv. 50 00:03:08,310 --> 00:03:11,940 Now, views.csv, I want to open it and not 51 00:03:11,940 --> 00:03:14,020 only just read the data inside of it. 52 00:03:14,020 --> 00:03:16,125 Reading being, I don't want to change anything, 53 00:03:16,125 --> 00:03:17,500 I just want to see what's inside. 54 00:03:17,500 --> 00:03:22,920 So I'll say as the second argument, to open r, which stands for reading mode. 55 00:03:22,920 --> 00:03:27,390 I'm going to just simply just read whatever is inside of views.csv. 56 00:03:27,390 --> 00:03:32,250 Now I'll go ahead and give a temporary name to the file I have opened. 57 00:03:32,250 --> 00:03:37,650 Here, I'm typing, with open views.csv r as file, meaning in this case, 58 00:03:37,650 --> 00:03:43,230 file refers to now the file I have opened, views.csv for reading. 59 00:03:43,230 --> 00:03:47,880 Now, within this block of code that I've opened up with with, 60 00:03:47,880 --> 00:03:51,750 I can do all kinds of things while this file is open. 61 00:03:51,750 --> 00:03:58,500 One thing I could do, as we said before, is use CSV.DictReader and pass as input, 62 00:03:58,500 --> 00:04:01,860 in this case, file, giving myself a reader 63 00:04:01,860 --> 00:04:05,160 I can use to loop over every kind of row that I'll 64 00:04:05,160 --> 00:04:08,680 see inside of this views.csv file. 65 00:04:08,680 --> 00:04:10,680 And we've also seen I can type this. 66 00:04:10,680 --> 00:04:15,758 For row in reader, meaning every row this reader gives back to me, 67 00:04:15,758 --> 00:04:17,550 I want to keep looping and looping over it, 68 00:04:17,550 --> 00:04:19,680 until I have no more rows to loop over. 69 00:04:19,680 --> 00:04:23,220 And I could, to make sure everything's working, type, print row, 70 00:04:23,220 --> 00:04:24,450 just like this. 71 00:04:24,450 --> 00:04:25,690 So what have I done? 72 00:04:25,690 --> 00:04:29,470 I've opened up views.csv, called it file, 73 00:04:29,470 --> 00:04:33,510 so long as we're inside of this indented block here, lines 8 through 10. 74 00:04:33,510 --> 00:04:38,010 I'm looping through every row I receive from this object called 75 00:04:38,010 --> 00:04:41,160 a DictReader, built into the CSV library, 76 00:04:41,160 --> 00:04:44,460 and I'll print the results as a row. 77 00:04:44,460 --> 00:04:50,400 Let's go ahead and run Python of views.py and hmm, 78 00:04:50,400 --> 00:04:54,430 here, we actually see a lot of dictionaries. 79 00:04:54,430 --> 00:04:56,710 I'll scroll up a little bit here. 80 00:04:56,710 --> 00:05:02,820 And we'll see our very first dictionary, id 1, 81 00:05:02,820 --> 00:05:06,690 which makes sense, because we have a column called, id. 82 00:05:06,690 --> 00:05:10,050 English title, The Great Wave off Kanagawa. 83 00:05:10,050 --> 00:05:13,080 Makes sense, because we have a heading, English title. 84 00:05:13,080 --> 00:05:16,450 And then Japanese title with this text right here. 85 00:05:16,450 --> 00:05:23,520 So it seems like we've gotten back every row in our CSV now as a dictionary. 86 00:05:23,520 --> 00:05:28,450 And this is likely the most convenient way to read your CSVs. 87 00:05:28,450 --> 00:05:30,640 Every row is its own dictionary. 88 00:05:30,640 --> 00:05:32,970 You can access the values at that row using 89 00:05:32,970 --> 00:05:37,470 the keys, which are the same names that you'll get at the top of your CSV file, 90 00:05:37,470 --> 00:05:38,550 for instance. 91 00:05:38,550 --> 00:05:41,740 So that seems to be going pretty well for us. 92 00:05:41,740 --> 00:05:43,990 Let's see what else we could do. 93 00:05:43,990 --> 00:05:48,930 I mean, our goal ultimately, is to open up these jpeg files and calculate 94 00:05:48,930 --> 00:05:52,380 how bright they are on a scale of 0 to 1. 95 00:05:52,380 --> 00:05:57,630 So notice how we said the id's in each of these rows mapped to 96 00:05:57,630 --> 00:06:00,130 or matched with the file names. 97 00:06:00,130 --> 00:06:06,760 So here again, The Great Wave has id 1, meaning it matches with the jpeg file, 98 00:06:06,760 --> 00:06:08,050 1.jpeg. 99 00:06:08,050 --> 00:06:11,740 So maybe let's focus on the id's here. 100 00:06:11,740 --> 00:06:14,840 As we said, every row is a dictionary. 101 00:06:14,840 --> 00:06:20,630 And I can access the value at a given row by typing in the column name, 102 00:06:20,630 --> 00:06:21,150 if you will. 103 00:06:21,150 --> 00:06:24,310 So here, our column name, our header was id. 104 00:06:24,310 --> 00:06:29,000 I can access 1 for this particular row, and every other row as well. 105 00:06:29,000 --> 00:06:31,840 2, 3, 4 5 and so on. 106 00:06:31,840 --> 00:06:34,420 I'll go ahead and run Python of views.py. 107 00:06:34,420 --> 00:06:39,220 And notice how now, I'm looping over and getting the id's 108 00:06:39,220 --> 00:06:41,650 from each particular row. 109 00:06:41,650 --> 00:06:45,710 So, then we can use this to calculate the brightness. 110 00:06:45,710 --> 00:06:49,550 Again, all calculate brightness needs is a file name. 111 00:06:49,550 --> 00:06:51,140 So I could maybe do this. 112 00:06:51,140 --> 00:06:57,670 I could say, brightness equals the result of calling calculate brightness, 113 00:06:57,670 --> 00:07:00,320 given some particular file name. 114 00:07:00,320 --> 00:07:04,120 And here, what I'll go ahead and type, is the file name 115 00:07:04,120 --> 00:07:07,180 I'm looking for on each iteration. 116 00:07:07,180 --> 00:07:13,480 I'll begin first with row, bracket, id, using a Python f string here. 117 00:07:13,480 --> 00:07:16,790 So if row id was 1, would have 1. 118 00:07:16,790 --> 00:07:19,360 If row id was 2, I would have 2. 119 00:07:19,360 --> 00:07:24,070 I'll then type .jpeg, which would complete the file name for me. 120 00:07:24,070 --> 00:07:27,550 So now what's happening, is calculate brightness is 121 00:07:27,550 --> 00:07:30,680 receiving for each row, the file name. 122 00:07:30,680 --> 00:07:33,220 It should look up to calculate the brightness from, 123 00:07:33,220 --> 00:07:36,430 and storing that result in brightness. 124 00:07:36,430 --> 00:07:40,340 I'll go ahead and print now the result of brightness. 125 00:07:40,340 --> 00:07:43,010 And why don't I try running this down below. 126 00:07:43,010 --> 00:07:47,080 I'll go ahead and type Python of views.py, and oops. 127 00:07:47,080 --> 00:07:49,470 Brightness does not seem to be defined. 128 00:07:49,470 --> 00:07:50,020 Aha. 129 00:07:50,020 --> 00:07:51,850 OK, so I should not have done this. 130 00:07:51,850 --> 00:07:56,170 Equals equals, we've seen before, that means comparing two values, 131 00:07:56,170 --> 00:07:58,590 setting them equal or testing if they are equal. 132 00:07:58,590 --> 00:08:00,500 What we want instead, is just equal. 133 00:08:00,500 --> 00:08:02,060 So typo on my part. 134 00:08:02,060 --> 00:08:04,990 I'll go ahead and now run Python of views.py 135 00:08:04,990 --> 00:08:08,570 and we'll see a lot of brightness values. 136 00:08:08,570 --> 00:08:12,070 And so we said before that in this case, we're actually getting brightness 137 00:08:12,070 --> 00:08:14,390 on a scale of 0 to 1. 138 00:08:14,390 --> 00:08:17,310 So, higher numbers mean more brightness. 139 00:08:17,310 --> 00:08:21,250 Lower numbers mean less brightness or more darkness, in this case. 140 00:08:21,250 --> 00:08:25,310 So these are pretty long numbers in terms of decimal places. 141 00:08:25,310 --> 00:08:27,900 So I could also round them if I wanted to, as well. 142 00:08:27,900 --> 00:08:31,435 I could type round, in this case, brightness 2, 143 00:08:31,435 --> 00:08:33,710 to round to two decimal places. 144 00:08:33,710 --> 00:08:36,260 I think we'll get a more friendly output here. 145 00:08:36,260 --> 00:08:40,090 I'll see for each file that I've opened and tested brightness for, 146 00:08:40,090 --> 00:08:43,570 some brightness value for each of those. 147 00:08:43,570 --> 00:08:48,790 But these numbers don't really mean much to me if they're not alongside, 148 00:08:48,790 --> 00:08:53,990 let's say, the file names, and the actual painting names, too. 149 00:08:53,990 --> 00:08:57,880 So, why don't we go ahead and try to make that happen for us as well? 150 00:08:57,880 --> 00:09:04,660 Well, what I need to do, is no longer just read in this CSV views.csv, 151 00:09:04,660 --> 00:09:09,930 I might also want to make a CSV, write some new one that has as part of it, 152 00:09:09,930 --> 00:09:12,030 some new column, let's say. 153 00:09:12,030 --> 00:09:14,280 Maybe one called, brightness, which actually 154 00:09:14,280 --> 00:09:18,120 includes the value we found for each, in this case, 155 00:09:18,120 --> 00:09:23,280 print that we have been thinking about in this collection of prints here. 156 00:09:23,280 --> 00:09:30,090 So, I can actually go ahead and open up not just one file, but two at one time. 157 00:09:30,090 --> 00:09:31,630 Using with. 158 00:09:31,630 --> 00:09:37,290 I can specify that I want to open one for reading right in here, but also, 159 00:09:37,290 --> 00:09:39,870 one for writing, as well. 160 00:09:39,870 --> 00:09:45,270 I'll type comma, and then open again, open in this case, maybe 161 00:09:45,270 --> 00:09:48,720 a new CSV called, analysis.csv. 162 00:09:48,720 --> 00:09:51,660 And I'll open this one, of course, in writing mode. 163 00:09:51,660 --> 00:09:53,700 W here stands for writing. 164 00:09:53,700 --> 00:09:57,150 And I'll give this one a name we can use inside 165 00:09:57,150 --> 00:10:01,590 of this indented block of code that's part of this with block. 166 00:10:01,590 --> 00:10:05,360 So now, I actually have two files open at once, 167 00:10:05,360 --> 00:10:10,760 one called views.csv in reading mode, which we're calling file for now. 168 00:10:10,760 --> 00:10:14,810 And one called analysis.csv in writing mode, 169 00:10:14,810 --> 00:10:17,030 which we're calling analysis for now. 170 00:10:17,030 --> 00:10:22,040 And for consistency, why don't I call file here, views, instead, 171 00:10:22,040 --> 00:10:25,670 and I'll update this down below, as well. 172 00:10:25,670 --> 00:10:29,280 So with these two files open, what can I do? 173 00:10:29,280 --> 00:10:34,860 I can both read from one file and write to the other. 174 00:10:34,860 --> 00:10:40,340 Now, to write to a CSV, we have a very similar object to DictReader, 175 00:10:40,340 --> 00:10:43,620 but instead, one called DictWriter. 176 00:10:43,620 --> 00:10:49,580 So maybe I'll make for myself a new object, one called writer, 177 00:10:49,580 --> 00:10:56,000 which is a CSV.DictWriter, which can take as input, dictionaries, 178 00:10:56,000 --> 00:11:00,590 and write them each as their own row in my new CSV file. 179 00:11:00,590 --> 00:11:05,610 I'll say that this DictWriter should be operating on the file we called, 180 00:11:05,610 --> 00:11:08,040 analysis, all the way over here. 181 00:11:08,040 --> 00:11:11,910 And now I have myself a new object called writer. 182 00:11:11,910 --> 00:11:16,570 But to create this writer, I still need more information. 183 00:11:16,570 --> 00:11:21,400 Notice how in views.csv, we actually have what's called a header. 184 00:11:21,400 --> 00:11:26,320 Some column names, if you will, id, English title, Japanese title. 185 00:11:26,320 --> 00:11:32,880 We decided to specify the same things for our new CSV, called analysis.csv. 186 00:11:32,880 --> 00:11:36,580 And we do so when we create this DictWriter. 187 00:11:36,580 --> 00:11:39,720 In fact, it has another argument called, field names, 188 00:11:39,720 --> 00:11:44,730 where field names refers to the header names you'll see up top. 189 00:11:44,730 --> 00:11:49,390 Well, what should field names for analysis be equal to? 190 00:11:49,390 --> 00:11:53,140 Well, they should be equal to, of course, the same column names as before. 191 00:11:53,140 --> 00:11:56,110 So id, English title, Japanese title. 192 00:11:56,110 --> 00:12:02,880 And I could type these out just like this, or I could make use of the reader 193 00:12:02,880 --> 00:12:03,610 itself. 194 00:12:03,610 --> 00:12:07,350 The reader actually stores those same field names 195 00:12:07,350 --> 00:12:10,150 in an attribute called, field names. 196 00:12:10,150 --> 00:12:13,590 So I can type reader.fieldnames. 197 00:12:13,590 --> 00:12:18,600 What we're saying here, is that this new file analysis should have the same field 198 00:12:18,600 --> 00:12:23,730 names, the same header as we see in views.csv, thanks to them 199 00:12:23,730 --> 00:12:29,100 being stored in reader.fieldnames, which is created from DictReader on this views 200 00:12:29,100 --> 00:12:30,600 file here. 201 00:12:30,600 --> 00:12:34,930 But now we also want a brightness column, a new field name here. 202 00:12:34,930 --> 00:12:37,960 So I could go ahead and combine various lists. 203 00:12:37,960 --> 00:12:40,383 This field names is a type of list. 204 00:12:40,383 --> 00:12:43,050 I can go ahead and add a new value to that list with this syntax 205 00:12:43,050 --> 00:12:45,430 here, plus some new list. 206 00:12:45,430 --> 00:12:48,450 And I'll go ahead and call this, brightness. 207 00:12:48,450 --> 00:12:54,270 So now I have for this new writer on this file, analysis, 208 00:12:54,270 --> 00:12:59,070 I have not just these headers, ID, English title, and Japanese title, 209 00:12:59,070 --> 00:13:02,520 but also, now one called, brightness, as well. 210 00:13:02,520 --> 00:13:06,060 And just to be sure we're making progress here, I could even go ahead 211 00:13:06,060 --> 00:13:09,450 and I could try to write the header. 212 00:13:09,450 --> 00:13:15,060 It turns out this writer object has a method called, write header, 213 00:13:15,060 --> 00:13:16,270 just like this. 214 00:13:16,270 --> 00:13:19,650 And if I were to run this code as is, we should hopefully 215 00:13:19,650 --> 00:13:24,900 see a new file called, analysis.csv with those headers in place. 216 00:13:24,900 --> 00:13:28,660 I'll run Python of views.py and we'll see, 217 00:13:28,660 --> 00:13:32,520 of course, our brightness being printed out, thanks to 12 through 14, 218 00:13:32,520 --> 00:13:39,450 but also, we'll see analysis.csv, which has all the same field names as before, 219 00:13:39,450 --> 00:13:43,440 the same headers, as well is one called, brightness. 220 00:13:43,440 --> 00:13:47,490 So now we have the basis for our analysis.csv, 221 00:13:47,490 --> 00:13:49,630 but we still need our rows. 222 00:13:49,630 --> 00:13:51,970 So in views.py, what can we do? 223 00:13:51,970 --> 00:13:57,450 We could probably, as we loop over the rows in this reader object, maybe 224 00:13:57,450 --> 00:13:59,560 also write some rows. 225 00:13:59,560 --> 00:14:04,350 Maybe, let's say, read in some row, find the brightness for that print, 226 00:14:04,350 --> 00:14:10,200 and then go ahead and write some new row in our analysis.csv over here. 227 00:14:10,200 --> 00:14:11,590 So let's try this. 228 00:14:11,590 --> 00:14:15,630 Maybe inside of this loop on line 12, I still 229 00:14:15,630 --> 00:14:19,680 want to calculate the brightness just like this, but rather than printing, 230 00:14:19,680 --> 00:14:25,390 what I really want to do, is write a new row. 231 00:14:25,390 --> 00:14:32,340 So writer, this CSV DictWriter object, has a method called, write row, 232 00:14:32,340 --> 00:14:36,400 allowing me to pass in a dictionary. 233 00:14:36,400 --> 00:14:42,180 A dictionary that will then be written to this file, in this case, analysis. 234 00:14:42,180 --> 00:14:46,440 Now, we can specify here the keys, which should 235 00:14:46,440 --> 00:14:50,130 match, in this case, the headers of our CSV file, 236 00:14:50,130 --> 00:14:54,360 id, English title, Japanese title, and brightness, 237 00:14:54,360 --> 00:14:59,640 and provide some values that this row should have for each of those columns. 238 00:14:59,640 --> 00:15:02,410 I'll go ahead and type ID, which is a key. 239 00:15:02,410 --> 00:15:05,400 Same thing that we was a field name, as a header here. 240 00:15:05,400 --> 00:15:08,300 I'll then go ahead and say, row bracket id. 241 00:15:08,300 --> 00:15:13,910 So in this case, the id, the value for id of this new row 242 00:15:13,910 --> 00:15:17,172 should match the id of this row. 243 00:15:17,172 --> 00:15:17,880 That makes sense. 244 00:15:17,880 --> 00:15:19,850 So first, 1, then 2. 245 00:15:19,850 --> 00:15:23,270 We'll have 1, then 2, as well, and analysis.csv. 246 00:15:23,270 --> 00:15:25,950 Now, really same thing for English title. 247 00:15:25,950 --> 00:15:30,710 That should be the same as the current rows, English title, where row here, 248 00:15:30,710 --> 00:15:33,230 refers to a row from views.csv. 249 00:15:33,230 --> 00:15:36,680 So again, if we had The Great Wave, we would also see The Great Wave 250 00:15:36,680 --> 00:15:39,860 as the English title in analysis.csv. 251 00:15:39,860 --> 00:15:42,090 Same thing here for Japanese title. 252 00:15:42,090 --> 00:15:47,460 Japanese title, we would have, of course, the Japanese title from the row. 253 00:15:47,460 --> 00:15:52,340 And now, here comes the change we're making here. 254 00:15:52,340 --> 00:15:56,780 If I wanted to include brightness, I can do that, as well. 255 00:15:56,780 --> 00:16:01,880 I can specify a key called, brightness, matching in this case, this column named 256 00:16:01,880 --> 00:16:05,520 brightness, and specify the value that should appear on 257 00:16:05,520 --> 00:16:09,900 any given row, in this case, the brightness we calculated up above. 258 00:16:09,900 --> 00:16:11,290 Let's go ahead and try this out. 259 00:16:11,290 --> 00:16:18,120 And again, here was our full code here. 260 00:16:18,120 --> 00:16:23,430 I'll go ahead and run down below, Python of views.py 261 00:16:23,430 --> 00:16:26,590 and we'll see no output, at least in our terminal. 262 00:16:26,590 --> 00:16:31,110 But now if I look at analysis.csv, well, I'll 263 00:16:31,110 --> 00:16:34,650 see the very same data from views.csv. 264 00:16:34,650 --> 00:16:37,690 And now this new column called, brightness, 265 00:16:37,690 --> 00:16:41,130 with the brightness value we calculated. 266 00:16:41,130 --> 00:16:43,030 Probably still want to round this though. 267 00:16:43,030 --> 00:16:48,870 So I'll go back to views.py and I will round brightness here, just like this. 268 00:16:48,870 --> 00:16:53,010 And then I'll go ahead and run Python of views.py again. 269 00:16:53,010 --> 00:16:57,900 If I go back and look, let's see, I'll have those rounded brightness values, 270 00:16:57,900 --> 00:16:59,430 as well. 271 00:16:59,430 --> 00:17:02,440 Now let's test visually to see if this is actually correct. 272 00:17:02,440 --> 00:17:08,400 So we said before that numbers closer to 0 were darker and numbers closer to 1 273 00:17:08,400 --> 00:17:09,670 were brighter. 274 00:17:09,670 --> 00:17:15,900 Now I have here on line a painting or print ID 3, 0.34, 275 00:17:15,900 --> 00:17:18,579 which seems like a pretty low value compared to the other ones. 276 00:17:18,579 --> 00:17:19,589 Let's go check this out. 277 00:17:19,589 --> 00:17:26,220 I'll go now to 3.jpeg and we'll see a pretty dark print. 278 00:17:26,220 --> 00:17:30,970 If I go back to analysis.csv here, let's find a pretty bright one. 279 00:17:30,970 --> 00:17:35,820 I think in this case, looks like a view of Mount Fuji. 280 00:17:35,820 --> 00:17:39,750 That one seems pretty bright, 0.75. 281 00:17:39,750 --> 00:17:44,340 If we look at this one, we'll see it is in fact, among the brighter of these, 282 00:17:44,340 --> 00:17:44,860 as well. 283 00:17:44,860 --> 00:17:49,230 So just to be clear, we had before 3, among the darker, 284 00:17:49,230 --> 00:17:52,510 and now 35 among the brighter. 285 00:17:52,510 --> 00:17:57,420 So a neat way of analyzing these images by their brightness. 286 00:17:57,420 --> 00:18:00,280 So I'd argue that our code seems to work. 287 00:18:00,280 --> 00:18:03,600 We're both reading and writing from a CSV, 288 00:18:03,600 --> 00:18:07,600 but our next step could be to improve the design of our code. 289 00:18:07,600 --> 00:18:13,390 Notice here on line 15 through 20, there's a lot of redundancy. 290 00:18:13,390 --> 00:18:17,400 We said before that we really want the same data from the rows or reading 291 00:18:17,400 --> 00:18:20,860 from to show up in the rows we're writing to. 292 00:18:20,860 --> 00:18:24,400 So it turns out, I actually don't need to make a brand new dictionary. 293 00:18:24,400 --> 00:18:28,508 I could probably just add on to the row dictionary itself. 294 00:18:28,508 --> 00:18:29,800 I'll show you what I mean here. 295 00:18:29,800 --> 00:18:36,750 If I go now to just underneath brightness, what I could try to do 296 00:18:36,750 --> 00:18:38,110 is the following. 297 00:18:38,110 --> 00:18:41,940 I could try to not make a whole new dictionary, 298 00:18:41,940 --> 00:18:46,660 but instead, maybe add on a new key to row. 299 00:18:46,660 --> 00:18:53,550 So recall, row here has all the values for ID, English title, Japanese title, 300 00:18:53,550 --> 00:18:54,490 and so on. 301 00:18:54,490 --> 00:18:58,710 All we're doing is adding on some new key with some new value, 302 00:18:58,710 --> 00:19:01,330 just like this, one called brightness. 303 00:19:01,330 --> 00:19:04,650 And if I wanted to, in this case, write this row, 304 00:19:04,650 --> 00:19:10,530 I could simply type write writer, writer.writerow, given the row 305 00:19:10,530 --> 00:19:14,760 we're currently reading, but now adding in this new key called, brightness. 306 00:19:14,760 --> 00:19:17,610 So much simpler, much fewer lines of code. 307 00:19:17,610 --> 00:19:23,350 I'll go ahead and run Python of views.py and we'll see the same results, as well. 308 00:19:23,350 --> 00:19:26,040 Of course, no longer rounded, so I'll go ahead and go back here 309 00:19:26,040 --> 00:19:29,230 and say, round this to two decimal places. 310 00:19:29,230 --> 00:19:32,880 And now I'll run Python of views.py and voila, 311 00:19:32,880 --> 00:19:38,220 there is our new CSV analysis.csv with that same information, 312 00:19:38,220 --> 00:19:40,830 plus brightness, as well. 313 00:19:40,830 --> 00:19:46,560 So this was our brief foray into both reading and writing CSVs, 314 00:19:46,560 --> 00:19:52,980 thanks to the CSV library and objects, like DictReader and DictWriter. 315 00:19:52,980 --> 00:19:55,760 We'll see you next time. 316 00:19:55,760 --> 00:20:00,000