CSV 파일이 보기에 더 어려운 이유
새로운 학생들에게 CSV 파일에서 가능한 잘못된 점이 무엇인지 물어보면, 그들은 보통 "별로 없어요 - 단지 텍스트일 뿐이죠."라고 대답합니다. 그러면 저는 그들에게 현실 세계의 CSV 악몽 모음을 보여주고, 그들의 자신감은 사라집니다. CSV는 "쉼표로 구분된 값"을 의미하지만, 그 이름은 오해의 소지가 있습니다. 실제로 CSV 파일은 쉼표, 세미콜론, 탭, 파이프 또는 데이터를 내보낸 사람이 그날 기분에 따라 사용한 어떤 문자로도 구분됩니다. 헤더가 있을 수도 있고, 없을 수도 있습니다. 텍스트 필드에 따옴표를 사용할 수도 있고, 불규칙하게 사용할 수도 있습니다. 날짜는 "MM/DD/YYYY", "DD-MM-YYYY", "YYYY/MM/DD" 또는 유닉스 타임스탬프 또는 엑셀 일련번호로 인코딩할 수도 있습니다(예, 정말로). CSV "표준"(RFC 4180)은 대부분의 소프트웨어가 기꺼이 무시하는 제안에 가깝습니다. Microsoft Excel은 지역 설정에 따라 CSV를 다르게 내보냅니다. Google Sheets는 형식에 대한 자체 아이디어가 있습니다. 데이터베이스 내보내기는 또 다른 일련의 규칙을 따릅니다. 그리고 여러 출처에서 데이터를 끌어오는 경우(기본적으로 모든 실제 프로젝트), 일관성 문제를 겪는 것이 보장됩니다. 여기서 특히 위험한 요소가 있는 이유는 다음과 같습니다: 판다스는 도움을 주려고 합니다. 판다스는 데이터 유형, 구분 기호, 인코딩 및 누락된 값에 대한 가정을 합니다. 때때로 이러한 가정은 정확합니다. 때때로 재앙적으로 잘못됩니다. 그리고 때때로 - 사라의 경우처럼 - 오류를 발생시키지 않고 단순히 데이터를 조용히 손상시키는 방식으로 잘못됩니다. 저는 학생들이 판다스가 날짜의 30%를 잘못 파싱한 데이터셋에 대해 며칠 동안 세련된 머신 러닝 모델을 구축하는 것을 본 적이 있습니다. 판다스가 통화 기호를 텍스트로 해석하고 모든 것을 문자열로 변환하여 수익 수치를 기반으로 비즈니스 권장 사항을 제시하는 분석가들을 지켜본 적이 있습니다. 판다스가 한 열에서는 "N/A"를 누락된 데이터로 읽었지만 다른 열에서는 문자 그대로 "N/A" 문자열로 읽어서 데이터 유형이 달라 문제를 일으킨 상황을 디버깅한 경험도 있습니다. 해결책은 CSV 파일을 피하는 것이 아닙니다 - 그것들은 어디에나 있고 종종 피할 수 없습니다. 해결책은 판다스가 CSV를 읽을 때 정확히 무엇을 하고 있는지를 이해하고, 그것이 만드는 모든 가정을 명시적으로 제어하는 것입니다. 이것이 이 튜토리얼의 주제입니다: "이게 잘 되기를 바란다"에서 "내 데이터에서 일어나는 일을 정확히 알고 있다"로 옮겨가는 것입니다.판다스 CSV 읽기 파이프라인: 실제로 발생하는 일
코드에 뛰어들기 전에, `pd.read_csv()`를 호출할 때 무대 뒤에서 무슨 일이 일어나는지를 이해해야 합니다. 이것은 학문적인 지식이 아닙니다 - 이 파이프라인을 이해하는 것은 CSV 파일로 어려움을 겪는 학생과 자신 있게 처리하는 학생을 구분하는 요소입니다. 판다스가 CSV 파일을 읽을 때, 여러 가지 뚜렷한 단계를 거칩니다: 1단계: 파일 접근 및 인코딩 감지 판다스는 파일을 열고 바이트를 텍스트로 디코딩하려고 시도합니다. 기본적으로 UTF-8 인코딩을 가정하는데, 이는 많은 현대 파일에는 유효하지만 오래된 데이터에서는 실망스럽게 실패합니다. 인코딩이 잘못되면, 판다스가 오류를 발생시키거나 조용히 문제 있는 문자를 물음표나 유니코드 대체 문자로 대체할 수 있습니다. 2단계: 구분 기호 감지 판다스는 처음 몇 줄을 살펴보아 열을 구분하는 문자가 무엇인지 추정합니다. 대개 꽤 잘 합니다. 그러나 "꽤 좋다"는 "항상 올바르다"와는 다릅니다. 처음 100행은 쉼표를 사용했지만 101행에서 누군가 파일을 수동으로 편집했기 때문에 세미콜론으로 바뀐 파일도 보았습니다. 3단계: 헤더 감지 판다스는 첫 번째 행에 열 이름이 포함되어 있다고 가정합니다. CSV에 헤더가 없다면, 판다스는 첫 번째 데이터 행을 열 이름으로 간주하여 혼란을 일으킵니다. CSV에 여러 헤더 행이 있는 경우(엑셀 내보내기에서 흔히 발생), 판다스는 첫 번째 것만 사용합니다. 4단계: 데이터 유형 추론 여기서부터는 정말 흥미롭습니다. 판다스는 각 열의 처음 몇 행을 검사하여 데이터 유형을 추정합니다. 숫자는 정수 또는 부동 소수가 됩니다. 텍스트는 문자열이 됩니다(또는 판다스 용어로 "객체" dtype). 날짜는... 글쎄요, 날짜는 복잡합니다. 판다스는 날짜처럼 보이는 경우에 파싱을 시도하지만, "날짜처럼 보이는" 정의가 귀하의 데이터와 일치하지 않을 수 있습니다. 5단계: 누락된 값 처리 판다스는 누락된 값으로 처리하는 문자열 목록을 내장하고 있습니다: "NA", "N/A", "NULL", "NaN", 빈 문자열 및 몇 가지 다른 것들. 데이터가 "MISSING" 또는 "---" 또는 "9999"와 같은 다른 규칙을 사용하면, 판다스는 이를 누락된 값으로 인식하지 않습니다. 이 각 단계는 가정을 포함합니다. 그리고 각 가정은 조용한 데이터 손상의 기회를 제공합니다. 신뢰할 수 있는 CSV 가져기의 핵심은 이러한 가정을 매개변수를 통해 명시적으로 만드는 것입니다.보이지 않는 소수점의 이야기
2023년 봄 집단의 학생 마커스에 대해 말씀드리겠습니다. 그는 유럽의 전자상거래 회사의 판매 데이터를 분석하고 있었고, 그의 분석 결과 평균 주문 값이 3분기에 불가사의하게 90% 감소했다고 나타났습니다. 그의 관리자 는 큰 비즈니스 문제에 직면했다고 생각하며 당황했습니다. 마커스는 이틀 동안 조사했습니다. 그는 데이터베이스 쿼리를 확인하고, 내보내기 프로세스를 검증하며, 텍스트 편집기에서 원시 CSV 파일을 검사했습니다 - 모든 것이 정상으로 보였습니다. CSV의 숫자는 정확했습니다: "1.234,56"은 유럽의 관습에 따라 천단위 구분 기호로 점, 소수점으로 쉼표를 사용하는 1,234 유로와 56 센트를 나타냅니다. 그러나 그가 그 데이터를 판다스에 로드했을 때, 그 숫자는 1.234 (일 점 이 삼 사)로 바뀌었습니다. 판다스는 점을 보고 이를 소수점으로 해석했기 때문입니다. 쉼표는? 판다스는 그걸 천 단위 구분 기호로 생각하고 무시했습니다. 그래서 "1.234,56"은 1.234가 되었고, "5.678,90"은 5.678이 되었습니다. 데이터셋의 모든 금액은 100배 이상 잘못되었습니다. 이를 수정하는 것은 간단했습니다. 문제를 식별한 후 `pd.read_csv()`에서 `decimal` 및 `thousands` 매개변수를 지정하면 되었습니다. 그러나 문제를 찾는 데는 며칠이 걸렸습니다. 처음 보기에 데이터는 합리적으로 보였기 때문입니다. 숫자는 숫자였고, 올바른 열에 있었으며, 그저 완전히 잘못된 것이었습니다. 이것이 제가 CSV 가져오는 것이 위험하다고 말하는 이유입니다. 오류가 항상 뚜렷하지 않습니다. 항상 예외를 발생시키지 않습니다. 때때로 귀하의 데이터는 그냥 조용히 잘못되어 버리고, 여러분은 그것을 기반으로 결정을 내린 후에야 알게 됩니다. 마커스의 이야기는 행복한 결말로 끝났습니다 - 우리는 실제 피해가 발생하기 전에 오류를 잡았습니다. 그러나 저는 업계 동료들로부터 데이터가 잘못되었음을 누군가가 알아차리기 전까지 임원 발표에 이른 분석에 대한 공포 이야기를 들었습니다. 한 회사는 손상된 CSV 가져오기를 바탕으로 수백만 달러의 투자 결정을 내릴 뻔했습니다.데이터 유형 이해하기: 올바른 가져기의 기초
이제 실질적인 접근을 해봅시다. 학생 프로젝트에서 흔히 발생하는 가장 일반적인 데이터 유형 문제와 이를 처리하는 방법을 보여주는 표입니다:| 데이터 유형 | 일반 문제 | 판다스 기본 동작 | 올바른 접근 |
|---|---|---|---|
| 정수 | 선행 0(우편번호), 텍스트로 저장된 큰 숫자 | int64로 변환하며, 선행 0을 삭제합니다. | 코드에는 dtype='str'를 사용하고, nullable 정수에는 dtype='Int64'를 사용하세요. |
| 부동 소수점 | 통화 기호, 천 단위 구분 기호, 유럽식 소수점 | 비숫자 문자가 있을 경우 객체(문자열)로 변환합니다. | 먼저 데이터를 정리하거나 converters 매개변수를 사용하세요. |
| 날짜 | 여러 형식, 시간대 문제, 엑셀 일련 날짜 | 형식이 분명하지 않으면 문자열로 유지됩니다. | 명시적 형식 문자열로 parse_dates를 사용하세요. |
| 부울 | 예/아니오, True/False, 1/0, Y/N 변형 | 문자열로 유지됩니다. | 가져온 후 변환기(converters)를 사용하거나 매핑을 하세요. |
| 카테고리 | 반복된 문자열 값(주, 국가, 제품 유형) | 객체로 저장되어 메모리를 낭비합니다. | 효율성을 위해 dtype='category'를 사용하세요. |
| 누락된 값 | 빈 문자열, "N/A", "NULL", "---", 9999 등 | 표준 NA 값만 인식합니다. | 사용자 정의 누락 표시기를 지정하기 위해 na_values 매개변수를 사용하세요. |
인코딩 문제: 왜 당신의 국제 데이터가 깨지는가
대부분의 학생들을 놀라게 하는 것 하나를 공유하겠습니다: 텍스트를 바이트로 인코딩하는 방법은 수십 가지가 있으며, CSV 파일은 어떤 인코딩을 사용하는지에 대한 메타데이터를 포함하지 않습니다. 그냥 추측해야 하며, 잘못 추측하면 데이터가 깨집니다."저는 고객 피드백 데이터를 분석하는 데 6개월을 보냈습니다. 그 당시 모든 액센트, 이모지, 비영어 문자가 가져오기 과정에서 손상되었다는 것을 깨닫기 전까지 아무도 눈치채지 못했습니다.我们的情感分析模型正以垃圾数据进行训练, 但由于英文评论看起来没问题, 所以没有人注意到。」- 과거 학생, 현재 포춘 500 기업의 머신 러닝 엔지니어UTF-8은 현대 표준이며 첫 번째 추측이 되어야 합니다. 그러나 오래된 시스템은 종종 라틴-1(ISO-8859-1이라고도 함), 윈도우 시스템은 CP1252를 사용할 수 있으며, 동아시아 데이터 작업 시 Shift-JIS, GB2312 또는 Big5를 만날 수 있습니다. 어떤 인코딩을 사용할지 어떻게 알 수 있을까요? 때때로 파일을 제공한 사람에게 물어볼 수 있습니다. 때때로 복잡하고 시간이 걸린다.