2014-09-19 2 views
1

나는 엑셀 스프레드 시트를 가지고있다. 나는 Access로 옮길 준비를하고 있고, 날짜 컬럼은 1963 년부터 1969 년까지, 1968 년 8 월에서 1968 년 9 월까지, 1972 년 3 월에서 73 년 24 -Jul, 1980 년 10 월 2 일, 1980 년 8 월 29 일, 1946 년 7 월 등. 나는 csv에 키 (지도 번호)와 날짜 열이 될 열을 가져 와서 csv에 다시 쓰고 있습니다. 범위는 아니지만 4 자리 숫자를 삭제할 수 있습니다. 그리고 나는 손으로 다시 포맷하기에 부족한 날과 2 자리 연도를 추출하는 방법을 잘 모른다. 내 코드는 매우 우아하고 아마 가장 좋은 방법이 아닙니다 :날짜로 카테고리

import csv, xlwt, re 

# create new Excel document and add sheet 
# from tempfile import TemporaryFile 
from xlwt import Workbook 
book = Workbook() 
sheet1 = book.add_sheet('Sheet 1') 

# populate first row with header 
sheet1.write(0,0,"Year") 
sheet1.write(0,1,"Map") 
sheet1.write(0,2,"As Entered") 

# count variable for populating sheet 
rowCount=0 

# open csv file and read 
with open('C:\dateTestMSDOs.csv', 'rb') as f: 
    reader=csv.reader(f) 
    for row in reader: 

     map = row[0] # first row is map number 
     dateRaw = row[1] # second row is raw date as entered 

     # write undated and blank entries 
     if dateRaw == 'undated': 
      yearStr = '0000' 
      rowCount +=1 
      sheet1.write(rowCount, 0, yearStr) 
      sheet1.write(rowCount, 1, map) 
      sheet1.write(rowCount, 2, dateRaw) 
      #print rowCount, yearStr, map, dateRaw, '\n' 
      yearStr='' 

     if dateRaw == '': 
      yearStr = 'NoEntry' 
      rowCount +=1 
      sheet1.write(rowCount, 0, yearStr) 
      sheet1.write(rowCount, 1, map) 
      sheet1.write(rowCount, 2, dateRaw) 
      #print rowCount, yearStr, map, dateRaw, '\n' 
      yearStr='' 

     # search and write instances of four consecutive digits 
     try: 
      year = re.search(r'\d\d\d\d', dateRaw) 
      yearStr= year.group() 
      #print yearStr, map, dateRaw 
      rowCount +=1 
      sheet1.write(rowCount, 0, yearStr) 
      sheet1.write(rowCount, 1, map) 
      sheet1.write(rowCount, 2, dateRaw) 
      #print rowCount, yearStr, map, dateRaw, '\n' 
      yearStr='' 

     # if none exist flag for cleaning spreadsheet and print 
     except: 
      #print 'Nope', map, dateRaw 
      rowCount +=1 
      yearStr='Format' 
      sheet1.write(rowCount, 0, yearStr) 
      sheet1.write(rowCount, 1, map) 
      sheet1.write(rowCount, 2, dateRaw) 
      #print rowCount, yearStr, map, dateRaw, '\n' 
      yearStr='' 
yearStr='' 
dateRaw='' 

book.save('D:\dateProperty.xls') 
print "Done!" 

내가 추가 열으로 월과 일 쓰기뿐만 아니라 다양한 항목의 두 번째 4 자리 날짜를 당겨 싶습니다.

+0

[datetime] (https://docs.python.org/2/library/datetime.html)의 날짜 형식을 살펴 보셨습니까? – N1B4

+0

[Pandas] (http://pandas.pydata.org)에는 강력한 날짜 분석 기능이 있습니다. 나는 그것을 살펴볼 것이다. – b10n

답변

1

이 경우 dateutil을 사용해보세요. 나는 아직도 당신이 다른 형식으로 좀 더 어려운 형식을 다룰 필요가 있다고 생각합니다. 아래의 샘플 구현을 참조하십시오

코드 :

import dateutil.parser as dateparser 

date_list = ['1963 to 1969', 
      'Aug. 1968 to Sept. 1968', 
      'Mar-73', 
      '24-Jul', 
      'Oct. 2 1980', 
      'Aug 29, 1980', 
      'July 1946', 
      'undated']   

for d in date_list: 
    if 'to' in d: 
     a, b = d.split('to') 
     # Get the higher number. Use min to get lower of two. 
     print max(dateparser.parse(a.strip()).year, dateparser.parse(b.strip()).year) 
    elif d == 'undated': 
     print '0000' 
    else: 
     yr = dateparser.parse(d).year 
     print yr 

결과 : 내가 볼 수

1969 
1968 
1973 
2014 
1980 
1980 
1946 
0000 
[Finished in 0.4s] 

만 눈부신 문제는 파서가 가정하기 때문에 24-Jul2014의 날짜를 반환한다는 것입니다 현재 날짜, 월 또는 연도, 즉 누락 된 구성 요소. Mar-73이 오늘의 20 일 등일 경우 1973-03-20이 될 것입니다.

+0

이 코드를 처리하는 것이 가장 좋은 방법이며 내 코드보다 낫습니다. 검색 가능한 매개 변수를 일 및 개월로 만들지 않기 위해 초점을 변경했을 때 나는 귀하의 게시물을 기억했을 것입니다. –

+0

필자는'pandas'를 대신 사용했을 것입니다. 그러나 데이터에 액세스 할 수 없다면, 이것이 제가 생각해 낼 수있는 최선의 방법입니다. – Manhattan

0

나는 이것이 단순한 정규식 검색을 사용한 다음 그룹 집합을 순회했는지 확실하지 않습니다. 그 함수는 정의 된 주어진 함수를 적용합니다. 일치하는 항목이 발견되면 regex_groups 변수에있는 함수는 다음 키가있는 사전을 반환해야합니다. start_day, start_month, start_year, end_day, end_month, end_year

그런 다음 원하는 값으로 무엇이든 할 수 있습니다. 명확히 가장 깨끗한 해결책이 아니지만 그것이 작동하는 한, 내가 알 수있는 한.

#!/usr/local/bin/python2.7 

import re 

# Crazy regex 
regex_pattern = '(?:(\d{4}) to (\d{4}))|(?:(\w+)\. (\d{4}) to (\w+)\. (\d{4}))|(?:(\w+)-(\d{2}))|(?:(\d{2})-(\w+))|(?:(\w+)\. (\d+), (\d{4}))|(?:(\w+) (\d+), (\d{4}))|(?:(\w+) (\d{4}))|(?:(\d{4}))' 

date_strings = [ 
    '1963 to 1969', 
    'Aug. 1968 to Sept. 1968', 
    '1972', 
    'Mar-73', 
    '24-Jul', 
    'Oct. 2, 1980', 
    'Aug 29, 1980', 
    'July 1946', 
] 

# Here you set the group matching functions that will be called for a matching group 
regex_groups = { 
    (1,2):  lambda group_matches: { 
    'start_day': '', 'start_month': '', 'start_year': group_matches[0], 
    'end_day': '', 'end_month': '', 'end_year': group_matches[1] 
    }, 
    (3,4,5,6): lambda group_matches: { 
    'start_day': '', 'start_month': group_matches[0], 'start_year': group_matches[1], 
    'end_day': '', 'end_month': group_matches[2], 'end_year': group_matches[3] 
    }, 
    (7,8):  lambda group_matches: { 
    'start_day': '', 'start_month': group_matches[0], 'start_year': group_matches[1], 
    'end_day': '', 'end_month': '', 'end_year': '' 
    }, 
    (9,10):  lambda group_matches: { 
    'start_day': group_matches[1], 'start_month': '', 'start_year': group_matches[0], 
    'end_day': '', 'end_month': '', 'end_year': '' 
    }, 
    (11,12,13): lambda group_matches: { 
    'start_day': group_matches[1], 'start_month': group_matches[0], 'start_year': group_matches[2], 
    'end_day': '', 'end_month': '', 'end_year': '' 
    }, 
    (14,15,16): lambda group_matches: { 
    'start_day': group_matches[1], 'start_month': group_matches[0], 'start_year': group_matches[2], 
    'end_day': '', 'end_month': '', 'end_year': '' 
    }, 
    (17,18): lambda group_matches: { 
    'start_day': '', 'start_month': group_matches[0], 'start_year': group_matches[1], 
    'end_day': '', 'end_month': '', 'end_year': '' 
    }, 
    (19,):  lambda group_matches: { 
    'start_day': '', 'start_month': '', 'start_year': group_matches[0], 
    'end_day': '', 'end_month': '', 'end_year': '' 
    }, 
} 

for ds in date_strings: 
    matches = re.search(regex_pattern, ds) 
    start_month = '' 
    start_year = '' 
    end_month = '' 
    end_year = '' 

    for regex_group, group_func in regex_groups.items(): 
    group_matches = [matches.group(sub_group_num) for sub_group_num in regex_group] 
    if all(group_matches): 
     match_data = group_func(group_matches) 
     print 
     print 'Matched:', ds 
     print '%s to %s' % ('-'.join([match_data['start_day'], match_data['start_month'], match_data['start_year']]), '-'.join([match_data['end_day'], match_data['end_month'], match_data['end_year']])) 

     # match_data is a dictionary with keys: 
     # * start_day 
     # * start_month 
     # * start_year 
     # * end_day 
     # * end_month 
     # * end_year 
     # If a group doesn't contain one of those items, then it is set to a blank string 

출력 :

Matched: 1963 to 1969 
--1963 to --1969 

Matched: Aug. 1968 to Sept. 1968 
-Aug-1968 to -Sept-1968 

Matched: 1972 
--1972 to -- 

Matched: Mar-73 
-Mar-73 to -- 

Matched: 24-Jul 
Jul--24 to -- 

Matched: Oct. 2, 1980 
2-Oct-1980 to -- 

Matched: Aug 29, 1980 
29-Aug-1980 to -- 

Matched: July 1946 
-July-1946 to -- 
+0

고마워요, Bryce. 이것은 시간이 얼마 남지 않고 작업 매개 변수가 포커스를 변경하기 전에 제가 가고 싶었던 곳입니다. 그래도이 코드는 보존 할 것입니다. 몇 달 안에 정리할 데이터가 쌓여서 더 효율적인 접근 방식 대신 완벽하게 적용됩니다. –

0
당신은 정규식을 사용하여 날짜의 모든 가능한 경우를 정의 할 수

, 뭔가 같은 :

import re 
s = ['1963 to 1969', 'Aug. 1968 to Sept. 1968', 
    '1972', 'Mar-73', '03-Jun', '24-Jul', 'Oct. 2, 1980', 'Oct. 26, 1980', 
    'Aug 29 1980', 'July 1946'] 


def get_year(date): 
    mm = re.findall("\d{4}", date) 
    if mm: 
     return mm 
    mm = re.search("\w+-(\d{2})", date) 
    if mm: 
     return [mm.group(1)] 

def get_month(date): 
    mm = re.findall("[A-Z][a-z]+", date) 
    if mm: 
     return mm 

def get_day(date): 
    d_expr = ["(\d|\d{2})\-[A-Z][a-z]+","[A-Z][a-z]+[\. ]+(\d|\d{2}),"] 
    for expr in d_expr: 
     mm = re.search(expr, date) 
     if mm: 
      return [mm.group(1)] 

d = {} 
m = {} 
y = {} 

for idx, date in enumerate(s): 
    d[idx] = get_day(date) 
    m[idx] = get_month(date) 
    y[idx] = get_year(date) 

print "Year Dict: ", y 
print "Month Dict: ", m 
print "Day Dict: ", d 

으로는 일, 월, 년의 사전을 얻을 결과 . 행을 채우는 데 사용할 수 있습니다.

출력 :

Year Dict: {0: ['1963', '1969'], 1: ['1968', '1968'], 2: ['1972'], 3: ['73'], 4: None, 5: None, 6: ['1980'], 7: ['1980'], 8: ['1980'], 9: ['1946']} 
Month Dict: {0: None, 1: ['Aug', 'Sept'], 2: None, 3: ['Mar'], 4: ['Jun'], 5: ['Jul'], 6: ['Oct'], 7: ['Oct'], 8: ['Aug'], 9: ['July']} 
Day Dict: {0: None, 1: None, 2: None, 3: None, 4: ['03'], 5: ['24'], 6: ['2'], 7: ['26'], 8: None, 9: None} 
+0

안녕하세요, 제안 해 주셔서 감사합니다. 나는 잘 작동하지 않는 코드를 게시 할 것이라고 생각했습니다. 출력 .xls는 LU 테이블로 데이터베이스로 가져와 잘 작동합니다. 단점은 모든 공백이나 추가 문자로 인해 문제가 발생하지만 단점의 위쪽은 원시 데이터 항목이 데이터베이스에서 단일 검색 가능 연도 범주의 출력을 준수해야한다는 것입니다 (이는 우리가 정착해야했던 것입니다. 기간, 일, 달 등을 다루고 있었다). –

0

는 혁신적인 제안을 주셔서 감사합니다. 고려한 후에 우리는 비교적 적은 양의 데이터 만이 그 세부 수준을 가지고 있었기 때문에 우리 데이터베이스에서 검색 할 수있는 것에서 하루와 달을 제거하기로 결정했습니다. 다음은 길고 지저분한 목록에서 필요한 데이터를 추출하고 생성하는 데 사용하는 코드입니다.

import csv, xlwt, re 
# create new Excel document and add sheet 
from xlwt import Workbook 
book = Workbook() 
sheet1 = book.add_sheet('Sheet 1') 

# populate first row with header 
sheet1.write(0,0,"MapYear_(Parsed)") 
sheet1.write(0,1,"Map_Number") 
sheet1.write(0,2,"As_Entered") 

# count variable for populating sheet 
rowCount=0 

# open csv file and read 
yearStr = '' 
with open('C:\mapsDateFix.csv', 'rb') as f: 
    reader=csv.reader(f) 
    for row in reader: 

     map = row[0] # first row is map number 
     dateRaw = row[1] # second row is raw date as entered 

     # write undated and blank entries 
     if dateRaw == 'undated': 
      yearStr = 'undated' 
      rowCount +=1 
      sheet1.write(rowCount, 0, yearStr) 
      sheet1.write(rowCount, 1, map) 
      sheet1.write(rowCount, 2, dateRaw) 
      #print rowCount, yearStr, map, dateRaw, '\n' 
      #yearStr='' 

     if yearStr != 'undated': 
      if dateRaw == '': 
       yearStr = 'NoEntry' 
       rowCount +=1 
       sheet1.write(rowCount, 0, yearStr) 
       sheet1.write(rowCount, 1, map) 
       sheet1.write(rowCount, 2, dateRaw) 
       #print rowCount, yearStr, map, dateRaw, '\n' 
       #yearStr='' 

     # search and write instances of four consecutive digits 
     if yearStr != dateRaw: 
      try: 
       year = re.search(r'\d\d\d\d', dateRaw) 
       yearStr= year.group() 
       #print yearStr, map, dateRaw 
       rowCount +=1 
       sheet1.write(rowCount, 0, yearStr) 
       sheet1.write(rowCount, 1, map) 
       sheet1.write(rowCount, 2, dateRaw) 
       #print rowCount, yearStr, map, dateRaw, '\n' 
       yearStr='' 

      # if none exist flag for cleaning spreadsheet and print 
      except: 
       #print 'Nope', map, dateRaw 
       rowCount +=1 
       yearStr='Format' 
       sheet1.write(rowCount, 0, yearStr) 
       sheet1.write(rowCount, 1, map) 
       sheet1.write(rowCount, 2, dateRaw) 
       #print rowCount, yearStr, map, dateRaw, '\n' 
       yearStr='' 
yearStr='' 
dateRaw='' 

book.save('D:\dateProperty.xls') 
print "Done!"