首页 文章

从CSV文件中提取特定数据

提问于
浏览
-2

我准备在一组样本学生数据上运行一些机器学习分类测试 . 我有CSV格式的数据,但我需要做一些提取,我希望有人可以给我一些关于如何在Python或R中做我需要的建议 . 这是一个数据样本:

enter image description here

正如您所看到的,目前已列出四名学生及其各自的成绩 . 我只需要检查在课程C5中得分为'W'的学生,但我还需要保留其他相应的成绩和课程 . 如果学生在课程C5中没有制作“W”,那么他们的所有数据都可以删除 .

例如:在上面的数据中,学生'C'和'D'可以完全从集合中移除,因为他们在课程C5中得分为'B'或根本没有取得它,但所有其他学生都得分为'W'在课程C5中因此应该保留在集合中 .

数据集相当大,我正在寻找比手动删除更准确的方法 .

提前致谢!

5 回答

  • 3

    你可以扫描两次表 . 第一遍记录应该留在数据集中的学生,第二遍记录写作 . 学生的分数可以是任何顺序,你仍然可以选择它们 .

    import csv
    import os
    
    input_filename = 'my.csv'
    output_filename = os.path.splitext(input_filename)[0] + '-out.csv'
    
    with open(input_filename) as infile:
        reader = csv.reader(infile)
        header = next(reader)
        table = [row for row in reader]
    
    w_students = set(row[0] for row in table if row[1]=='C5' and row[2]=='W')
    
    with open(output_filename, 'w') as outfile:
        writer = csv.writer(outfile)
        writer.writerow(header)
        for row in table:
            if row[0] in w_students:
                writer.writerow(row)
    
  • 4

    由于其他人都在使用python进行回答,我将提供三种基于R的替代方案:

    dat <- data.frame(Student = c(rep('A', 5), rep('B', 5), rep('C', 6), rep('D', 4)),
                      Course = paste0('C', c(1:5, 1:5, 1:6, 1:4)),
                      Grade = c('A', 'B', 'A', 'C', 'W', 'B', 'C', 'D', 'A', 'W', 'A',
                          'A', 'A', 'C', 'B', 'A', 'W', 'F', 'A', 'B'),
                      stringsAsFactors = FALSE)
    

    Base [操作员

    studs <- dat$Student[ dat$Course == 'C5' & dat$Grade == 'W' ]
    studs
    ## [1] "A" "B"
    dat[dat$Student %in% studs, ]
    ##    Student Course Grade
    ## 1        A     C1     A
    ## 2        A     C2     B
    ## 3        A     C3     A
    ## 4        A     C4     C
    ## 5        A     C5     W
    ## 6        B     C1     B
    ## 7        B     C2     C
    ## 8        B     C3     D
    ## 9        B     C4     A
    ## 10       B     C5     W
    

    基本子集功能

    我个人并不使用 subset (和some argue它可能并不总是像你期望的那样),但它干净利落地阅读:

    studs <- subset(dat, Course == 'C5' & Grade == 'W')$Student
    dat[dat$Student %in% studs, ]
    ##    Student Course Grade
    ## 1        A     C1     A
    ## 2        A     C2     B
    ## 3        A     C3     A
    ## ...
    

    包dplyr

    Hadleyverse提供 dplyr 包w

    dat %>%
        group_by(Student) %>%
        do(if (any((.$Course == 'C5') & (.$Grade == 'W'))) . else data.frame())
    ## Source: local data frame [10 x 3]
    ## Groups: Student
    ##    Student Course Grade
    ## 1        A     C1     A
    ## 2        A     C2     B
    ## 3        A     C3     A
    ## ...
    

    使用 dplyr 可能有更有效的方法 . (事实上,我感觉相当蛮力 . )

    表现

    既然你说"the dataset is rather large,"我会提出第一个( [ )是最快的 . 使用这些数据它的速度大约是其两倍,但是如果数据量大得多,我只能看到20%的差异 . dplyr 并不比基数快,实际上至少慢了一个数量级(有了这个实现,需要注意);许多人争论较大的数据,更容易阅读和维护 .

  • 0

    你应该使用pandas . pandas Dataframe是一种与excel表非常相似的数据结构 .

    Read CSV

    import pandas as pd
    df = pd.read_csv('filename.csv')
    

    Filter students:

    filtered = df.groupby('Student')\
                 .filter(lambda x: (x['Course'] == 'C5').any() and 
                                   (x['Grade'] == 'W').any())
    

    Write results to disk

    filtered.to_csv('filtered.csv', index=None)
    

    编辑(@Anzel):或者你可以这样做:

    df = df.set_index('student')
    filtered = (df['Course'] == 'C5') & (df['Grade'] == 'W')
    df.loc[list(df[filtered].index)].to_csv('filtered.csv')
    
  • 0

    免责声明:我对R几乎一无所知,我只讨厌Excel,所以我只想回答python . 它只是纯Python,虽然如果你不介意使用外部库,elyase的答案是好的 .

    您案例中最有趣的模块是csv . 此外, collections.namedtuple 允许您在对象上创建一个很好的抽象 .

    import csv
    import collections
    
    with open(filename, 'rb') as f:
        reader = csv.reader(f)
        # Read the first line to get the headers
        Record = collections.namedtuple("Record", next(reader))
        # Read the rest of the file into a list
        records = [Record(*line) for line in reader]
    
    # This will give you objects with a nice interface (fields with header
    # names). For your example, you would have fields like record.Course
    # and record.Grade.
    

    获得记录列表后,构建包含学生成绩的字典很容易,特别是如果您使用 collections.defaultdict

    students = collections.defaultdict(list)
    for record in records:
        students[record.Student].add(record)
    

    过滤可以通过各种方式完成,但我喜欢发电机和所有...

    def record_filter(records):
        has_grade = False
        for r in record:
            if r.Course == 'C5' and r.Grade == 'w':
                has_grade = True
        return has_grade
    
    filtered_students = {key: value for key, value in students
            if record_filter(value)}
    
  • 1

    我有一个不同的数据文件

    % cat datastu.csv
    1,1,1
    1,2,1
    2,1,1
    3,2,4
    3,1,2
    3,3,3
    4,1,3
    4,2,4
    5,1,0
    5,2,5
    %
    

    和不同的要求,即 course==2grade==4 . 有了这些前提,这就是我的计划

    % cat datastu.py
    # save if course == 2 and grade == 4
    
    inf = open('datastu.csv')
    data = {}
    for l in inf:
        s,c,g = l.strip().split(',')
        data.setdefault(s,[])
        data[s].append((c,g))
    
    for s in data:
        if ('2','4') in data[s]:
            for c, g in data[s]: print ','.join((s,c,g))
    

    它的输出是

    3,2,4
    3,1,2
    3,3,3
    4,1,3
    4,2,4
    

    我确信您可以轻松地根据您的要求调整我的方法 .

相关问题