分类 技术 下的文章

这是如何建立 数据科学作品集 Data Science Portfolio 系列文章中的第一篇。如果你喜欢这篇文章并且想知道此系列的下一篇文章何时发表,你可以在页面底部订阅

数据科学公司们在决定雇佣一个人时越来越看重其作品集。其中一个原因就是 作品集 portfolio 是分析一个人真实技能的最好方式。好消息是,作品集是完全可以被你掌控的。如果你在其上投入了一些工作,你就能够做出一个令那些公司印象深刻的作品集结果。

建立一个高质量作品集的第一步就是知道展示什么技能。那些公司们主要希望数据科学工作者拥有的技能,或者说他们主要希望作品集所展示的技能是:

  • 表达能力
  • 合作能力
  • 专业技能
  • 解释数据的能力
  • 有目标和有积极性的

任何一个好的作品集都由多个工程构成,每一个工程都会展示 1-2 个上面所说的点。这是涵盖了“如何完成一个完整的数据科学作品集”系列文章的第一篇。在这篇文章中,我们将会涵括如何完成你的第一项数据科学作品集工程,并且对此进行有效的解释。在最后,你将会得到一个帮助展示你表达能力和解释数据能力的工程。

用数据讲故事

数据科学是表达的基础。你将会在数据中发现一些观点,并且找出一个高效的方式来向他人表达这些,之后向他们展示你所开展的课题。数据科学最关键的手法之一就是能够用数据讲述一个清晰的故事。一个清晰的故事能够使你的观点更加引人注目,并且能使别人理解你的想法。

数据科学中的故事是一个讲述你发现了什么,你怎么发现它的,并且它意味着什么的故事。例如假使发现你公司的收入相对去年减少了百分之二十。这并不能够确定原因,你可能需要和其它人沟通为什么收入会减少,并且在尝试修复它。

用数据讲故事主要包含:

  • 理解并确定上下文
  • 从多角度发掘
  • 使用有趣的表示方法
  • 使用多种数据来源
  • 一致的表述

用来讲述数据的故事最有效率的工具就是 Jupyter notebook。如果你不熟悉,此处有一个好的教程。Jupyter notebook 允许你交互式的发掘数据,并且将你的结果分享到多个网站,包括 Github。分享你的结果有助于合作研究和其他人拓展你的分析。

在这篇文章中,我们将使用 Jupyter notebook,以及 Pandas 和 matplotlib 这样的 Python 库。

为你的数据科学工程选择一个主题

建立一个工程的第一步就是决定你的主题。你要让你的主题是你兴趣所在,有动力去挖掘。进行数据挖掘时,为了完成而完成和有兴趣完成的区别是很明显的。这个步骤是值得花费时间的,所以确保你找到了你真正感兴趣的东西。

一个寻找主题的好方法就是浏览不同的数据集并且寻找感兴趣的部分。这里有一些作为起点的好的网站:

真实世界中的数据科学,你经常无法找到可以浏览的合适的单个数据集。你可能需要聚合多个独立的数据源,或者做数量庞大的数据清理。如果该主题非常吸引你,这是值得这样做的,并且也能更好的展示你的技能。

关于这篇文章的主题,我们将使用纽约市公立学校的数据,我们可以在这里找到它。

选择主题

这对于项目全程来说是十分重要的。因为主题能很好的限制项目的范围,并且它能够使我们知道它可以被完成。比起一个没有足够动力完成的工程来说,添加到一个完成的工程更加容易。

所以,我们将关注高中的学术评估测试,伴随着多种人口统计和它们的其它数据。关于学习评估测试, 或者说 SAT,是美国高中生申请大学前的测试。大学在做判定时将考虑该成绩,所以高分是十分重要的。考试分为三个阶段,每个阶段总分为 800。全部分数为 2400(即使这个前后更改了几次,在数据中总分还是 2400)。高中经常通过平均 SAT分数进行排名,并且 SAT 是评判高中有多好的标准。

因为由关于 SAT 分数对于美国中某些种族群体是不公平的,所以对纽约市这个数据做分析能够对 SAT 的公平性有些许帮助。

我们在这里有 SAT 成绩的数据集,并且在这里有包含了每所高中的信息的数据集。这些将构成我们的工程的基础,但是我们将加入更多的信息来创建有趣的分析。

补充数据

如果你已经有了一个很好的主题,拓展其它可以提升主题或者更深入挖掘数据的的数据集是一个好的选择。在前期十分适合做这些工作,你将会有尽可能多的数据来构建你的工程。数据越少意味着你会太早的放弃了你的工程。

在本项目中,在包含人口统计信息和测试成绩的网站上有一些相关的数据集。

这些是我们将会用到的所有数据集:

  • 学校 SAT 成绩 – 纽约市每所高中的 SAT 成绩。
  • 学校出勤情况 – 纽约市每所学校的出勤信息。
  • 数学成绩 – 纽约市每所学校的数学成绩。
  • 班级规模 - 纽约市每所学校课堂人数信息。
  • AP 成绩 - 高阶位考试,在美国,通过 AP 测试就能获得大学学分。
  • 毕业去向 – 由百分之几的学生毕业了,和其它去向信息。
  • 人口统计 – 每个学校的人口统计信息。
  • 学校问卷 – 学校的家长、教师,学生的问卷。
  • 学校分布地图 – 包含学校的区域布局信息,因此我们能将它们在地图上标出。

(LCTT 译注:高阶位考试(AP)是美国和加拿大的一个由大学委员会创建的计划,该计划为高中学生提供大学水平的课程和考试。 美国学院和大学可以授予在考试中获得高分的学生的就学和课程学分。)

这些数据作品集之间是相互关联的,并且我们能够在开始分析之前进行合并。

获取背景信息

在开始分析数据之前,搜索一些背景信息是有必要的。我们知道这些有用的信息:

  • 纽约市被分为五个不同的辖区
  • 纽约市的学校被分配到几个学区,每个学区都可能包含数十所学校。
  • 数据集中的学校并不全是高中,所以我们需要对数据进行一些清理工作。
  • 纽约市的每所学校都有自己单独的编码,被称为‘DBN’,即区域行政编号。
  • 为了通过区域进行数据聚合,我们可以使用地图区域信息来绘制逐区差异。

理解数据

为了真正的理解数据信息,你需要花费时间来挖掘和阅读数据。因此,每个数据链接都有数据的描述信息,并伴随着相关列。就像是我们拥有的高中 SAT 成绩信息,也包含图像和其它信息的数据集。

我们可以运行一些代码来读取数据。我们将使用 Jupyter notebook 来挖掘数据。下面的代码将会执行以下操作:

  • 循环遍历我们下载的所有数据文件。
  • 将文件读取到 Pandas DataFrame
  • 将所有数据框架导入 Python 数据库中。

In [100]:

import pandas
import numpy as np

files = ["ap_2010.csv", "class_size.csv", "demographics.csv", "graduation.csv", "hs_directory.csv", "math_test_results.csv", "sat_results.csv"]

data = {}
for f in files:
    d = pandas.read_csv("schools/{0}".format(f))
    data[f.replace(".csv", "")] = d

一旦我们将数据读入,我们就可以使用 DataFrames 的 head 方法打印每个 DataFrame 的前五行。

In [103]:

for k,v in data.items():
    print("\n" + k + "\n")
    print(v.head())
math_test_results

      DBN Grade  Year      Category  Number Tested Mean Scale Score Level 1 #  \
0  01M015     3  2006  All Students             39              667         2
1  01M015     3  2007  All Students             31              672         2
2  01M015     3  2008  All Students             37              668         0
3  01M015     3  2009  All Students             33              668         0
4  01M015     3  2010  All Students             26              677         6

  Level 1 % Level 2 # Level 2 % Level 3 # Level 3 % Level 4 # Level 4 %  \
0      5.1%        11     28.2%        20     51.3%         6     15.4%
1      6.5%         3      9.7%        22       71%         4     12.9%
2        0%         6     16.2%        29     78.4%         2      5.4%
3        0%         4     12.1%        28     84.8%         1        3%
4     23.1%        12     46.2%         6     23.1%         2      7.7%

  Level 3+4 # Level 3+4 %
0          26       66.7%
1          26       83.9%
2          31       83.8%
3          29       87.9%
4           8       30.8%

ap_2010

      DBN                             SchoolName AP Test Takers   \
0  01M448           UNIVERSITY NEIGHBORHOOD H.S.              39
1  01M450                 EAST SIDE COMMUNITY HS              19
2  01M515                    LOWER EASTSIDE PREP              24
3  01M539         NEW EXPLORATIONS SCI,TECH,MATH             255
4  02M296  High School of Hospitality Management               s

  Total Exams Taken Number of Exams with scores 3 4 or 5
0                49                                   10
1                21                                    s
2                26                                   24
3               377                                  191
4                 s                                    s

sat_results

      DBN                                    SCHOOL NAME  \
0  01M292  HENRY STREET SCHOOL FOR INTERNATIONAL STUDIES
1  01M448            UNIVERSITY NEIGHBORHOOD HIGH SCHOOL
2  01M450                     EAST SIDE COMMUNITY SCHOOL
3  01M458                      FORSYTH SATELLITE ACADEMY
4  01M509                        MARTA VALLE HIGH SCHOOL

  Num of SAT Test Takers SAT Critical Reading Avg. Score SAT Math Avg. Score  \
0                     29                             355                 404
1                     91                             383                 423
2                     70                             377                 402
3                      7                             414                 401
4                     44                             390                 433

  SAT Writing Avg. Score
0                    363
1                    366
2                    370
3                    359
4                    384

class_size

   CSD BOROUGH SCHOOL CODE                SCHOOL NAME GRADE  PROGRAM TYPE  \
0    1       M        M015  P.S. 015 Roberto Clemente     0K       GEN ED
1    1       M        M015  P.S. 015 Roberto Clemente     0K          CTT
2    1       M        M015  P.S. 015 Roberto Clemente     01       GEN ED
3    1       M        M015  P.S. 015 Roberto Clemente     01          CTT
4    1       M        M015  P.S. 015 Roberto Clemente     02       GEN ED

  CORE SUBJECT (MS CORE and 9-12 ONLY) CORE COURSE (MS CORE and 9-12 ONLY)  \
0                                    -                                   -
1                                    -                                   -
2                                    -                                   -
3                                    -                                   -
4                                    -                                   -

  SERVICE CATEGORY(K-9* ONLY)  NUMBER OF STUDENTS / SEATS FILLED  \
0                           -                               19.0
1                           -                               21.0
2                           -                               17.0
3                           -                               17.0
4                           -                               15.0

   NUMBER OF SECTIONS  AVERAGE CLASS SIZE  SIZE OF SMALLEST CLASS  \
0                 1.0                19.0                    19.0
1                 1.0                21.0                    21.0
2                 1.0                17.0                    17.0
3                 1.0                17.0                    17.0
4                 1.0                15.0                    15.0

   SIZE OF LARGEST CLASS DATA SOURCE  SCHOOLWIDE PUPIL-TEACHER RATIO
0                   19.0         ATS                             NaN
1                   21.0         ATS                             NaN
2                   17.0         ATS                             NaN
3                   17.0         ATS                             NaN
4                   15.0         ATS                             NaN

demographics

      DBN                       Name  schoolyear fl_percent  frl_percent  \
0  01M015  P.S. 015 ROBERTO CLEMENTE    20052006       89.4          NaN
1  01M015  P.S. 015 ROBERTO CLEMENTE    20062007       89.4          NaN
2  01M015  P.S. 015 ROBERTO CLEMENTE    20072008       89.4          NaN
3  01M015  P.S. 015 ROBERTO CLEMENTE    20082009       89.4          NaN
4  01M015  P.S. 015 ROBERTO CLEMENTE    20092010                    96.5

   total_enrollment prek   k grade1 grade2    ...     black_num black_per  \
0               281   15  36     40     33    ...            74      26.3
1               243   15  29     39     38    ...            68      28.0
2               261   18  43     39     36    ...            77      29.5
3               252   17  37     44     32    ...            75      29.8
4               208   16  40     28     32    ...            67      32.2

  hispanic_num hispanic_per white_num white_per male_num male_per female_num  \
0          189         67.3         5       1.8    158.0     56.2      123.0
1          153         63.0         4       1.6    140.0     57.6      103.0
2          157         60.2         7       2.7    143.0     54.8      118.0
3          149         59.1         7       2.8    149.0     59.1      103.0
4          118         56.7         6       2.9    124.0     59.6       84.0

  female_per
0       43.8
1       42.4
2       45.2
3       40.9
4       40.4

[5 rows x 38 columns]

graduation

    Demographic     DBN                            School Name    Cohort  \
0  Total Cohort  01M292  HENRY STREET SCHOOL FOR INTERNATIONAL      2003
1  Total Cohort  01M292  HENRY STREET SCHOOL FOR INTERNATIONAL      2004
2  Total Cohort  01M292  HENRY STREET SCHOOL FOR INTERNATIONAL      2005
3  Total Cohort  01M292  HENRY STREET SCHOOL FOR INTERNATIONAL      2006
4  Total Cohort  01M292  HENRY STREET SCHOOL FOR INTERNATIONAL  2006 Aug

   Total Cohort Total Grads - n Total Grads - % of cohort Total Regents - n  \
0             5               s                         s                 s
1            55              37                     67.3%                17
2            64              43                     67.2%                27
3            78              43                     55.1%                36
4            78              44                     56.4%                37

  Total Regents - % of cohort Total Regents - % of grads  \
0                           s                          s
1                       30.9%                      45.9%
2                       42.2%                      62.8%
3                       46.2%                      83.7%
4                       47.4%                      84.1%

             ...            Regents w/o Advanced - n  \
0            ...                                   s
1            ...                                  17
2            ...                                  27
3            ...                                  36
4            ...                                  37

  Regents w/o Advanced - % of cohort Regents w/o Advanced - % of grads  \
0                                  s                                 s
1                              30.9%                             45.9%
2                              42.2%                             62.8%
3                              46.2%                             83.7%
4                              47.4%                             84.1%

  Local - n Local - % of cohort   Local - % of grads Still Enrolled - n  \
0         s                   s                    s                  s
1        20               36.4%                54.1%                 15
2        16                 25%  37.200000000000003%                  9
3         7                  9%                16.3%                 16
4         7                  9%                15.9%                 15

  Still Enrolled - % of cohort Dropped Out - n Dropped Out - % of cohort
0                            s               s                         s
1                        27.3%               3                      5.5%
2                        14.1%               9                     14.1%
3                        20.5%              11                     14.1%
4                        19.2%              11                     14.1%

[5 rows x 23 columns]

hs_directory

      dbn                                        school_name       boro  \
0  17K548                Brooklyn School for Music & Theatre   Brooklyn
1  09X543                   High School for Violin and Dance      Bronx
2  09X327        Comprehensive Model School Project M.S. 327      Bronx
3  02M280     Manhattan Early College School for Advertising  Manhattan
4  28Q680  Queens Gateway to Health Sciences Secondary Sc...     Queens

  building_code    phone_number    fax_number grade_span_min  grade_span_max  \
0          K440    718-230-6250  718-230-6262              9              12
1          X400    718-842-0687  718-589-9849              9              12
2          X240    718-294-8111  718-294-8109              6              12
3          M520  718-935-3477             NaN              9              10
4          Q695    718-969-3155  718-969-3552              6              12

  expgrade_span_min  expgrade_span_max  \
0               NaN                NaN
1               NaN                NaN
2               NaN                NaN
3                 9               14.0
4               NaN                NaN

                         ...                          \
0                        ...
1                        ...
2                        ...
3                        ...
4                        ...

                                          priority02  \
0                    Then to New York City residents
1  Then to New York City residents who attend an ...
2  Then to Bronx students or residents who attend...
3  Then to New York City residents who attend an ...
4  Then to Districts 28 and 29 students or residents

                                          priority03  \
0                                                NaN
1                Then to Bronx students or residents
2  Then to New York City residents who attend an ...
3          Then to Manhattan students or residents
4               Then to Queens students or residents

                            priority04                       priority05  \
0                                  NaN                              NaN
1      Then to New York City residents                              NaN
2  Then to Bronx students or residents  Then to New York City residents
3      Then to New York City residents                              NaN
4      Then to New York City residents                              NaN

  priority06  priority07 priority08  priority09 priority10  \
0        NaN         NaN        NaN         NaN        NaN
1        NaN         NaN        NaN         NaN        NaN
2        NaN         NaN        NaN         NaN        NaN
3        NaN         NaN        NaN         NaN        NaN
4        NaN         NaN        NaN         NaN        NaN

                                          Location 1
0  883 Classon Avenue\nBrooklyn, NY 11225\n(40.67...
1  1110 Boston Road\nBronx, NY 10456\n(40.8276026...
2  1501 Jerome Avenue\nBronx, NY 10452\n(40.84241...
3  411 Pearl Street\nNew York, NY 10038\n(40.7106...
4  160-20 Goethals Avenue\nJamaica, NY 11432\n(40...

[5 rows x 58 columns]

我们可以开始在数据作品集中观察有用的部分:

  • 大部分数据集包含 DBN 列。
  • 一些条目看起来在地图上标出会很有趣,特别是 Location 1,这列在一个很长的字符串里面包含了位置信息。
  • 有些数据集会出现每所学校对应多行数据(DBN 数据重复),这意味着我们要进行预处理。

统一数据

为了使工作更简单,我们将需要将全部零散的数据集统一为一个。这将使我们能够快速跨数据集对比数据列。因此,我们需要找到相同的列将它们统一起来。请查看上面的输出数据, DBN 出现在多个数据集中,它看起来可以作为共同列。

如果我们用 google 搜索 DBN New York City Schools,我们在此得到了结果。它解释了 DBN 是每个学校独特的编码。我们将挖掘数据集,特别是政府数据集。这通常需要做一些工作来找出每列的含义,或者每个数据集的意图。

现在主要的问题是这两个数据集 class_sizehs_directory,没有 DBN 列。在 hs_directory 数据中是 dbn,那么我们只需重命名即可,或者将它复制到新的名为 DBN 的列中。在 class_size 数据中,我们将需要尝试不同的方法。

DBN 列:

In [5]:

data["demographics"]["DBN"].head()

Out[5]:

0    01M015
1    01M015
2    01M015
3    01M015
4    01M015
Name: DBN, dtype: object

如果我们查看 class_size数据,我们将看到前五行如下:

In [4]:

data["class_size"].head()

Out[4]:

CSDBOROUGHSCHOOL CODESCHOOL NAMEGRADEPROGRAM TYPECORE SUBJECT (MS CORE and 9-12 ONLY)CORE COURSE (MS CORE and 9-12 ONLY)SERVICE CATEGORY(K-9* ONLY)NUMBER OF STUDENTS / SEATS FILLEDNUMBER OF SECTIONSAVERAGE CLASS SIZESIZE OF SMALLEST CLASSSIZE OF LARGEST CLASSDATA SOURCESCHOOLWIDE PUPIL-TEACHER RATIO
01MM015P.S. 015 Roberto Clemente0KGEN ED---19.01.019.019.019.0ATSNaN
11MM015P.S. 015 Roberto Clemente0KCTT---21.01.021.021.021.0ATSNaN
21MM015P.S. 015 Roberto Clemente01GEN ED---17.01.017.017.017.0ATSNaN
31MM015P.S. 015 Roberto Clemente01CTT---17.01.017.017.017.0ATSNaN
41MM015P.S. 015 Roberto Clemente02GEN ED---15.01.015.015.015.0ATSNaN

正如上面所见,DBN 实际上是 CSDBOROUGHSCHOOL CODE 的组合。对那些不熟悉纽约市的人来说,纽约由五个行政区组成。每个行政区是一个组织单位,并且有着相当于美国大城市一样的面积。DBN 全称为行政区域编号。看起来就像 CSD 是区域,BOROUGH 是行政区,并且当与 SCHOOL CODE 合并时就组成了 DBN。这里并没有寻找像这个数据这样的内在规律的系统方法,这需要一些探索和努力来发现。

现在我们已经知道了 DBN 的组成,那么我们就可以将它加入到 class_sizehs_directory 数据集中了:

In [ ]:

data["class_size"]["DBN"] = data["class_size"].apply(lambda x: "{0:02d}{1}".format(x["CSD"], x["SCHOOL CODE"]), axis=1)
data["hs_directory"]["DBN"] = data["hs_directory"]["dbn"]

加入问卷

最可能值得一看的数据集之一就是学生、家长和老师关于学校质量的问卷了。这些问卷包含了每所学校的安全程度、教学水平等。在我们合并数据集之前,让我们添加问卷数据。在真实世界的数据科学工程中,你经常会在分析过程中碰到有趣的数据,并且希望合并它。使用像 Jupyter notebook 一样灵活的工具将允许你快速添加一些新的代码,并且重新开始你的分析。

因此,我们将添加问卷数据到我们的 data 文件夹,并且合并所有之前的数据。问卷数据分为两个文件,一个包含所有的学校,一个包含 75 学区。我们将需要写一些代码来合并它们。之后的代码我们将:

  • 使用 windows-1252 编码读取所有学校的问卷。
  • 使用 windows-1252 编码读取所有 75 号学区的问卷。
  • 添加指示每个数据集所在学区的标志。
  • 使用 DataFrame 的 concat 方法将数据集合并为一个。

In [66]:

survey1 = pandas.read_csv("schools/survey_all.txt", delimiter="\t", encoding='windows-1252')
survey2 = pandas.read_csv("schools/survey_d75.txt", delimiter="\t", encoding='windows-1252')
survey1["d75"] = False
survey2["d75"] = True
survey = pandas.concat([survey1, survey2], axis=0)

一旦我们将问卷合并,这里将会有一些混乱。我们希望我们合并的数据集列数最少,那么我们将可以轻易的进行列之间的对比并找出其间的关联。不幸的是,问卷数据有很多列并不是很有用:

In [16]:

survey.head()

Out[16]:

N\_pN\_sN\_tacap11acas11acat11acatot11bncomp11coms11...tq8c1tq8c2tq8c3tq8c4t\_q9tq91tq92tq93tq94tq95
090.0NaN22.07.8NaN7.97.9M0157.6NaN...29.067.05.00.0NaN5.014.052.024.05.0
1161.0NaN34.07.8NaN9.18.4M0197.6NaN...74.021.06.00.0NaN3.06.03.078.09.0
2367.0NaN42.08.6NaN7.58.0M0208.3NaN...33.035.020.013.0NaN3.05.016.070.05.0
3151.0145.029.08.57.47.87.9M0348.25.9...21.045.028.07.0NaN0.018.032.039.011.0
490.0NaN23.07.9NaN8.18.0M0637.9NaN...59.036.05.00.0NaN10.05.010.060.015.0

5 rows × 2773 columns

我们可以通过查看数据文件夹中伴随问卷数据下载下来的文件来解决这个问题。它告诉我们们数据中重要的部分是哪些:

我们可以去除 survey 数据集中多余的列:

In [17]:

survey["DBN"] = survey["dbn"]
survey_fields = ["DBN", "rr_s", "rr_t", "rr_p", "N_s", "N_t", "N_p", "saf_p_11", "com_p_11", "eng_p_11", "aca_p_11", "saf_t_11", "com_t_11", "eng_t_10", "aca_t_11", "saf_s_11", "com_s_11", "eng_s_11", "aca_s_11", "saf_tot_11", "com_tot_11", "eng_tot_11", "aca_tot_11",]
survey = survey.loc[:,survey_fields]
data["survey"] = survey
survey.shape

Out[17]:

(1702, 23)

请确保理你已经了解了每个数据集的内容和相关联的列,这能节约你之后大量的时间和精力:

精简数据集

如果我们查看某些数据集,包括 class_size,我们将立刻发现问题:

In [18]:

data["class_size"].head()

Out[18]:

CSDBOROUGHSCHOOL CODESCHOOL NAMEGRADEPROGRAM TYPECORE SUBJECT (MS CORE and 9-12 ONLY)CORE COURSE (MS CORE and 9-12 ONLY)SERVICE CATEGORY(K-9* ONLY)NUMBER OF STUDENTS / SEATS FILLEDNUMBER OF SECTIONSAVERAGE CLASS SIZESIZE OF SMALLEST CLASSSIZE OF LARGEST CLASSDATA SOURCESCHOOLWIDE PUPIL-TEACHER RATIODBN
01MM015P.S. 015 Roberto Clemente0KGEN ED---19.01.019.019.019.0ATSNaN01M015
11MM015P.S. 015 Roberto Clemente0KCTT---21.01.021.021.021.0ATSNaN01M015
21MM015P.S. 015 Roberto Clemente01GEN ED---17.01.017.017.017.0ATSNaN01M015
31MM015P.S. 015 Roberto Clemente01CTT---17.01.017.017.017.0ATSNaN01M015
41MM015P.S. 015 Roberto Clemente02GEN ED---15.01.015.015.015.0ATSNaN01M015

每所高中都有许多行(正如你所见的重复的 DBNSCHOOL NAME)。然而,如果我们看向 sat_result 数据集,每所高中只有一行:

In [21]:

data["sat_results"].head()

Out[21]:

DBNSCHOOL NAMENum of SAT Test TakersSAT Critical Reading Avg. ScoreSAT Math Avg. ScoreSAT Writing Avg. Score
001M292HENRY STREET SCHOOL FOR INTERNATIONAL STUDIES29355404363
101M448UNIVERSITY NEIGHBORHOOD HIGH SCHOOL91383423366
201M450EAST SIDE COMMUNITY SCHOOL70377402370
301M458FORSYTH SATELLITE ACADEMY7414401359
401M509MARTA VALLE HIGH SCHOOL44390433384

为了合并这些数据集,我们将需要找到方法将数据集精简到如 class_size 般一行对应一所高中。否则,我们将不能将 SAT 成绩与班级大小进行比较。我们通过首先更好的理解数据,然后做一些合并来完成。class_size 数据集像 GRADEPROGRAM TYPE,每个学校有多个数据对应。为了将每个范围内的数据变为一个数据,我们将大部分重复行过滤掉,在下面的代码中我们将会:

  • 只从 class_size 中选择 GRADE 范围为 09-12 的行。
  • 只从 class_size 中选择 PROGRAM TYPEGEN ED 的行。
  • class_sizeDBN 分组,然后取每列的平均值。重要的是,我们将找到每所学校班级大小(class_size)平均值。
  • 重置索引,将 DBN 重新加到列中。

In [68]:

class_size = data["class_size"]
class_size = class_size[class_size["GRADE "] == "09-12"]
class_size = class_size[class_size["PROGRAM TYPE"] == "GEN ED"]
class_size = class_size.groupby("DBN").agg(np.mean)
class_size.reset_index(inplace=True)
data["class_size"] = class_size

精简其它数据集

接下来,我们将需要精简 demographic 数据集。这里有每个学校收集多年的数据,所以这里每所学校有许多重复的行。我们将只选取 schoolyear 最近的可用行:

In [69]:

demographics = data["demographics"]
demographics = demographics[demographics["schoolyear"] == 20112012]
data["demographics"] = demographics

我们需要精简 math_test_results 数据集。这个数据集被 GradeYear 划分。我们将只选取单一学年的一个年级。

In [70]:

data["math_test_results"] = data["math_test_results"][data["math_test_results"]["Year"] == 2011]
data["math_test_results"] = data["math_test_results"][data["math_test_results"]["Grade"] == '8']

最后,graduation需要被精简:

In [71]:

data["graduation"] = data["graduation"][data["graduation"]["Cohort"] == "2006"]
data["graduation"] = data["graduation"][data["graduation"]["Demographic"] == "Total Cohort"]

在完成工程的主要部分之前数据清理和挖掘是十分重要的。有一个高质量的,一致的数据集将会使你的分析更加快速。

计算变量

计算变量可以通过使我们的比较更加快速来加快分析速度,并且能使我们做到本无法做到的比较。我们能做的第一件事就是从分开的列 SAT Math Avg. ScoreSAT Critical Reading Avg. ScoreSAT Writing Avg. Score 计算 SAT 成绩:

  • 将 SAT 列数值从字符转化为数字。
  • 将所有列相加以得到 sat_score,即 SAT 成绩。

In [72]:

cols = ['SAT Math Avg. Score', 'SAT Critical Reading Avg. Score', 'SAT Writing Avg. Score']
for c in cols:
    data["sat_results"][c] = data["sat_results"][c].convert_objects(convert_numeric=True)

data['sat_results']['sat_score'] = data['sat_results'][cols[0]] + data['sat_results'][cols[1]] + data['sat_results'][cols[2]]

接下来,我们将需要进行每所学校的坐标位置分析,以便我们制作地图。这将使我们画出每所学校的位置。在下面的代码中,我们将会:

  • Location 1 列分析出经度和维度。
  • 转化 lat(经度)和 lon(维度)为数字。

In [73]:

data["hs_directory"]['lat'] = data["hs_directory"]['Location 1'].apply(lambda x: x.split("\n")[-1].replace("(", "").replace(")", "").split(", ")[0])
data["hs_directory"]['lon'] = data["hs_directory"]['Location 1'].apply(lambda x: x.split("\n")[-1].replace("(", "").replace(")", "").split(", ")[1])

for c in ['lat', 'lon']:
    data["hs_directory"][c] = data["hs_directory"][c].convert_objects(convert_numeric=True)

现在,我们将输出每个数据集来查看我们有了什么数据:

In [74]:

for k,v in data.items():
    print(k)
    print(v.head())
math_test_results
        DBN Grade  Year      Category  Number Tested Mean Scale Score  \
111  01M034     8  2011  All Students             48              646
280  01M140     8  2011  All Students             61              665
346  01M184     8  2011  All Students             49              727
388  01M188     8  2011  All Students             49              658
411  01M292     8  2011  All Students             49              650

    Level 1 # Level 1 % Level 2 # Level 2 % Level 3 # Level 3 % Level 4 #  \
111        15     31.3%        22     45.8%        11     22.9%         0
280         1      1.6%        43     70.5%        17     27.9%         0
346         0        0%         0        0%         5     10.2%        44
388        10     20.4%        26     53.1%        10     20.4%         3
411        15     30.6%        25       51%         7     14.3%         2

    Level 4 % Level 3+4 # Level 3+4 %
111        0%          11       22.9%
280        0%          17       27.9%
346     89.8%          49        100%
388      6.1%          13       26.5%
411      4.1%           9       18.4%
survey
      DBN  rr_s  rr_t  rr_p    N_s   N_t    N_p  saf_p_11  com_p_11  eng_p_11  \
0  01M015   NaN    88    60    NaN  22.0   90.0       8.5       7.6       7.5
1  01M019   NaN   100    60    NaN  34.0  161.0       8.4       7.6       7.6
2  01M020   NaN    88    73    NaN  42.0  367.0       8.9       8.3       8.3
3  01M034  89.0    73    50  145.0  29.0  151.0       8.8       8.2       8.0
4  01M063   NaN   100    60    NaN  23.0   90.0       8.7       7.9       8.1

      ...      eng_t_10  aca_t_11  saf_s_11  com_s_11  eng_s_11  aca_s_11  \
0     ...           NaN       7.9       NaN       NaN       NaN       NaN
1     ...           NaN       9.1       NaN       NaN       NaN       NaN
2     ...           NaN       7.5       NaN       NaN       NaN       NaN
3     ...           NaN       7.8       6.2       5.9       6.5       7.4
4     ...           NaN       8.1       NaN       NaN       NaN       NaN

   saf_tot_11  com_tot_11  eng_tot_11  aca_tot_11
0         8.0         7.7         7.5         7.9
1         8.5         8.1         8.2         8.4
2         8.2         7.3         7.5         8.0
3         7.3         6.7         7.1         7.9
4         8.5         7.6         7.9         8.0

[5 rows x 23 columns]
ap_2010
      DBN                             SchoolName AP Test Takers   \
0  01M448           UNIVERSITY NEIGHBORHOOD H.S.              39
1  01M450                 EAST SIDE COMMUNITY HS              19
2  01M515                    LOWER EASTSIDE PREP              24
3  01M539         NEW EXPLORATIONS SCI,TECH,MATH             255
4  02M296  High School of Hospitality Management               s

  Total Exams Taken Number of Exams with scores 3 4 or 5
0                49                                   10
1                21                                    s
2                26                                   24
3               377                                  191
4                 s                                    s
sat_results
      DBN                                    SCHOOL NAME  \
0  01M292  HENRY STREET SCHOOL FOR INTERNATIONAL STUDIES
1  01M448            UNIVERSITY NEIGHBORHOOD HIGH SCHOOL
2  01M450                     EAST SIDE COMMUNITY SCHOOL
3  01M458                      FORSYTH SATELLITE ACADEMY
4  01M509                        MARTA VALLE HIGH SCHOOL

  Num of SAT Test Takers  SAT Critical Reading Avg. Score  \
0                     29                            355.0
1                     91                            383.0
2                     70                            377.0
3                      7                            414.0
4                     44                            390.0

   SAT Math Avg. Score  SAT Writing Avg. Score  sat_score
0                404.0                   363.0     1122.0
1                423.0                   366.0     1172.0
2                402.0                   370.0     1149.0
3                401.0                   359.0     1174.0
4                433.0                   384.0     1207.0
class_size
      DBN  CSD  NUMBER OF STUDENTS / SEATS FILLED  NUMBER OF SECTIONS  \
0  01M292    1                            88.0000            4.000000
1  01M332    1                            46.0000            2.000000
2  01M378    1                            33.0000            1.000000
3  01M448    1                           105.6875            4.750000
4  01M450    1                            57.6000            2.733333

   AVERAGE CLASS SIZE  SIZE OF SMALLEST CLASS  SIZE OF LARGEST CLASS  \
0           22.564286                   18.50              26.571429
1           22.000000                   21.00              23.500000
2           33.000000                   33.00              33.000000
3           22.231250                   18.25              27.062500
4           21.200000                   19.40              22.866667

   SCHOOLWIDE PUPIL-TEACHER RATIO
0                             NaN
1                             NaN
2                             NaN
3                             NaN
4                             NaN
demographics
       DBN                                              Name  schoolyear  \
6   01M015  P.S. 015 ROBERTO CLEMENTE                           20112012
13  01M019  P.S. 019 ASHER LEVY                                 20112012
20  01M020  PS 020 ANNA SILVER                                  20112012
27  01M034  PS 034 FRANKLIN D ROOSEVELT                         20112012
35  01M063  PS 063 WILLIAM MCKINLEY                             20112012

   fl_percent  frl_percent  total_enrollment prek    k grade1 grade2  \
6         NaN         89.4               189   13   31     35     28
13        NaN         61.5               328   32   46     52     54
20        NaN         92.5               626   52  102    121     87
27        NaN         99.7               401   14   34     38     36
35        NaN         78.9               176   18   20     30     21

      ...     black_num black_per hispanic_num hispanic_per white_num  \
6     ...            63      33.3          109         57.7         4
13    ...            81      24.7          158         48.2        28
20    ...            55       8.8          357         57.0        16
27    ...            90      22.4          275         68.6         8
35    ...            41      23.3          110         62.5        15

   white_per male_num male_per female_num female_per
6        2.1     97.0     51.3       92.0       48.7
13       8.5    147.0     44.8      181.0       55.2
20       2.6    330.0     52.7      296.0       47.3
27       2.0    204.0     50.9      197.0       49.1
35       8.5     97.0     55.1       79.0       44.9

[5 rows x 38 columns]
graduation
     Demographic     DBN                            School Name Cohort  \
3   Total Cohort  01M292  HENRY STREET SCHOOL FOR INTERNATIONAL   2006
10  Total Cohort  01M448    UNIVERSITY NEIGHBORHOOD HIGH SCHOOL   2006
17  Total Cohort  01M450             EAST SIDE COMMUNITY SCHOOL   2006
24  Total Cohort  01M509                MARTA VALLE HIGH SCHOOL   2006
31  Total Cohort  01M515  LOWER EAST SIDE PREPARATORY HIGH SCHO   2006

    Total Cohort Total Grads - n Total Grads - % of cohort Total Regents - n  \
3             78              43                     55.1%                36
10           124              53                     42.7%                42
17            90              70                     77.8%                67
24            84              47                       56%                40
31           193             105                     54.4%                91

   Total Regents - % of cohort Total Regents - % of grads  \
3                        46.2%                      83.7%
10                       33.9%                      79.2%
17         74.400000000000006%                      95.7%
24                       47.6%                      85.1%
31                       47.2%                      86.7%

              ...            Regents w/o Advanced - n  \
3             ...                                  36
10            ...                                  34
17            ...                                  67
24            ...                                  23
31            ...                                  22

   Regents w/o Advanced - % of cohort Regents w/o Advanced - % of grads  \
3                               46.2%                             83.7%
10                              27.4%                             64.2%
17                74.400000000000006%                             95.7%
24                              27.4%                             48.9%
31                              11.4%                               21%

   Local - n Local - % of cohort Local - % of grads Still Enrolled - n  \
3          7                  9%              16.3%                 16
10        11                8.9%              20.8%                 46
17         3                3.3%               4.3%                 15
24         7  8.300000000000001%              14.9%                 25
31        14                7.3%              13.3%                 53

   Still Enrolled - % of cohort Dropped Out - n Dropped Out - % of cohort
3                         20.5%              11                     14.1%
10                        37.1%              20       16.100000000000001%
17                        16.7%               5                      5.6%
24                        29.8%               5                        6%
31                        27.5%              35       18.100000000000001%

[5 rows x 23 columns]
hs_directory
      dbn                                        school_name       boro  \
0  17K548                Brooklyn School for Music & Theatre   Brooklyn
1  09X543                   High School for Violin and Dance      Bronx
2  09X327        Comprehensive Model School Project M.S. 327      Bronx
3  02M280     Manhattan Early College School for Advertising  Manhattan
4  28Q680  Queens Gateway to Health Sciences Secondary Sc...     Queens

  building_code    phone_number    fax_number grade_span_min  grade_span_max  \
0          K440    718-230-6250  718-230-6262              9              12
1          X400    718-842-0687  718-589-9849              9              12
2          X240    718-294-8111  718-294-8109              6              12
3          M520  718-935-3477             NaN              9              10
4          Q695    718-969-3155  718-969-3552              6              12

  expgrade_span_min  expgrade_span_max    ...      \
0               NaN                NaN    ...
1               NaN                NaN    ...
2               NaN                NaN    ...
3                 9               14.0    ...
4               NaN                NaN    ...

                        priority05 priority06 priority07 priority08  \
0                              NaN        NaN        NaN        NaN
1                              NaN        NaN        NaN        NaN
2  Then to New York City residents        NaN        NaN        NaN
3                              NaN        NaN        NaN        NaN
4                              NaN        NaN        NaN        NaN

  priority09  priority10                                         Location 1  \
0        NaN         NaN  883 Classon Avenue\nBrooklyn, NY 11225\n(40.67...
1        NaN         NaN  1110 Boston Road\nBronx, NY 10456\n(40.8276026...
2        NaN         NaN  1501 Jerome Avenue\nBronx, NY 10452\n(40.84241...
3        NaN         NaN  411 Pearl Street\nNew York, NY 10038\n(40.7106...
4        NaN         NaN  160-20 Goethals Avenue\nJamaica, NY 11432\n(40...

      DBN        lat        lon
0  17K548  40.670299 -73.961648
1  09X543  40.827603 -73.904475
2  09X327  40.842414 -73.916162
3  02M280  40.710679 -74.000807
4  28Q680  40.718810 -73.806500

[5 rows x 61 columns]

合并数据集

现在我们已经完成了全部准备工作,我们可以用 DBN 列将数据组合在一起了。最终,我们将会从原始数据集得到一个有着上百列的数据集。当我们合并它们,请注意有些数据集中会丢失了 sat_result 中出现的高中。为了解决这个问题,我们需要使用 outer 方法来合并缺少行的数据集,这样我们就不会丢失数据。在实际分析中,缺少数据是很常见的。能够展示解释和解决数据缺失的能力是构建一个作品集的重要部分。

你可以在阅读关于不同类型的合并。

接下来的代码,我们将会:

  • 循环遍历 data 文件夹中的每一个条目。
  • 输出条目中的非唯一的 DBN 码数量。
  • 决定合并策略 - innerouter
  • 使用 DBN 列将条目合并到 DataFrame full 中。

In [75]:

flat_data_names = [k for k,v in data.items()]
flat_data = [data[k] for k in flat_data_names]
full = flat_data[0]
for i, f in enumerate(flat_data[1:]):
    name = flat_data_names[i+1]
    print(name)
    print(len(f["DBN"]) - len(f["DBN"].unique()))
    join_type = "inner"
    if name in ["sat_results", "ap_2010", "graduation"]:
        join_type = "outer"
    if name not in ["math_test_results"]:
        full = full.merge(f, on="DBN", how=join_type)

full.shape
survey
0
ap_2010
1
sat_results
0
class_size
0
demographics
0
graduation
0
hs_directory
0

Out[75]:

(374, 174)

添加值

现在我们有了我们的 full 数据框架,我们几乎拥有分析需要的所有数据。虽然这里有一些缺少的部分。我们可能将AP 考试结果与 SAT 成绩相关联,但是我们首先需要将这些列转化为数字,然后填充缺失的数据。

In [76]:

cols = ['AP Test Takers ', 'Total Exams Taken', 'Number of Exams with scores 3 4 or 5']

for col in cols:
    full[col] = full[col].convert_objects(convert_numeric=True)

full[cols] = full[cols].fillna(value=0)

然后我们将需要计算表示学校所在学区的 school_dist列。这将是我们匹配学区并且使用我们之前下载的区域地图画出地区级别的地图。

In [77]:

full["school_dist"] = full["DBN"].apply(lambda x: x[:2])

最终,我们将需要用该列的平均值填充缺失的数据到 full 中。那么我们就可以计算关联了:

In [79]:

full = full.fillna(full.mean())

计算关联

一个挖掘数据并查看哪些列与你所关心的问题有联系的好方法来就是计算关联。这将告诉你哪列与你所关心的列更加有关联。你可以通过 Pandas DataFrames 的 corr 方法来完成。越接近 0 则关联越小。越接近 1 则正相关越强,越接近 -1 则负关联越强:

In [80]:

full.corr()['sat_score']

Out[80]:

Year                                             NaN
Number Tested                           8.127817e-02
rr_s                                    8.484298e-02
rr_t                                   -6.604290e-02
rr_p                                    3.432778e-02
N_s                                     1.399443e-01
N_t                                     9.654314e-03
N_p                                     1.397405e-01
saf_p_11                                1.050653e-01
com_p_11                                2.107343e-02
eng_p_11                                5.094925e-02
aca_p_11                                5.822715e-02
saf_t_11                                1.206710e-01
com_t_11                                3.875666e-02
eng_t_10                                         NaN
aca_t_11                                5.250357e-02
saf_s_11                                1.054050e-01
com_s_11                                4.576521e-02
eng_s_11                                6.303699e-02
aca_s_11                                8.015700e-02
saf_tot_11                              1.266955e-01
com_tot_11                              4.340710e-02
eng_tot_11                              5.028588e-02
aca_tot_11                              7.229584e-02
AP Test Takers                          5.687940e-01
Total Exams Taken                       5.585421e-01
Number of Exams with scores 3 4 or 5    5.619043e-01
SAT Critical Reading Avg. Score         9.868201e-01
SAT Math Avg. Score                     9.726430e-01
SAT Writing Avg. Score                  9.877708e-01
                                            ...
SIZE OF SMALLEST CLASS                  2.440690e-01
SIZE OF LARGEST CLASS                   3.052551e-01
SCHOOLWIDE PUPIL-TEACHER RATIO                   NaN
schoolyear                                       NaN
frl_percent                            -7.018217e-01
total_enrollment                        3.668201e-01
ell_num                                -1.535745e-01
ell_percent                            -3.981643e-01
sped_num                                3.486852e-02
sped_percent                           -4.413665e-01
asian_num                               4.748801e-01
asian_per                               5.686267e-01
black_num                               2.788331e-02
black_per                              -2.827907e-01
hispanic_num                            2.568811e-02
hispanic_per                           -3.926373e-01
white_num                               4.490835e-01
white_per                               6.100860e-01
male_num                                3.245320e-01
male_per                               -1.101484e-01
female_num                              3.876979e-01
female_per                              1.101928e-01
Total Cohort                            3.244785e-01
grade_span_max                         -2.495359e-17
expgrade_span_max                                NaN
zip                                    -6.312962e-02
total_students                          4.066081e-01
number_programs                         1.166234e-01
lat                                    -1.198662e-01
lon                                    -1.315241e-01
Name: sat_score, dtype: float64

这给了我们一些我们需要探索的内在规律:

  • total_enrollmentsat_score 强相关,这是令人惊讶的,因为你曾经认为越小的学校越专注于学生就会取得更高的成绩。
  • 女生所占学校的比例(female_per) 与 SAT 成绩呈正相关,而男生所占学生比例(male_per)成负相关。
  • 没有问卷与 SAT 成绩成正相关。
  • SAT 成绩有明显的种族不平等(white_perasian_perblack_perhispanic_per)。
  • ell_percent 与 SAT 成绩明显负相关。

每一个条目都是一个挖掘和讲述数据故事的潜在角度。

设置上下文

在我们开始数据挖掘之前,我们将希望设置上下文,不仅为了我们自己,也是为了其它阅读我们分析的人。一个好的方法就是建立挖掘图表或者地图。因此,我们将在地图标出所有学校的位置,这将有助于读者理解我们所探索的问题。

在下面的代码中,我们将会:

  • 建立纽约市为中心的地图。
  • 为城市里的每所高中添加一个标记。
  • 显示地图。

In [82]:

import folium
from folium import plugins

schools_map = folium.Map(location=[full['lat'].mean(), full['lon'].mean()], zoom_start=10)
marker_cluster = folium.MarkerCluster().add_to(schools_map)
for name, row in full.iterrows():
    folium.Marker([row["lat"], row["lon"]], popup="{0}: {1}".format(row["DBN"], row["school_name"])).add_to(marker_cluster)
schools_map.create_map('schools.html')
schools_map

Out[82]:

这个地图十分有用,但是不容易查看纽约哪里学校最多。因此,我们将用热力图来代替它:

In [84]:

schools_heatmap = folium.Map(location=[full['lat'].mean(), full['lon'].mean()], zoom_start=10)
schools_heatmap.add_children(plugins.HeatMap([[row["lat"], row["lon"]] for name, row in full.iterrows()]))
schools_heatmap.save("heatmap.html")
schools_heatmap

Out[84]:

区域级别映射

热力图能够很好的标出梯度,但是我们将需要更结构化的画出不同城市之间的 SAT 分数差距。学区是一个图形化这个信息的很好的方式,就像每个区域都有自己的管理者。纽约市有数十个学区,并且每个区域都是一个小的地理区域。

我们可以通过学区来计算 SAT 分数,然后将它们画在地图上。在下面的代码中,我们将会:

  • 通过学区对 full 进行分组。
  • 计算每个学区的每列的平均值。
  • 去掉 school_dist 字段头部的 0,然后我们就可以匹配地理数据了。

In [ ]:

district_data = full.groupby("school_dist").agg(np.mean)
district_data.reset_index(inplace=True)
district_data["school_dist"] = district_data["school_dist"].apply(lambda x: str(int(x)))

我们现在将可以画出 SAT 在每个学区的平均值了。因此,我们将会读取 GeoJSON 中的数据,转化为每个区域的形状,然后通过 school_dist 列对每个区域图形和 SAT 成绩进行匹配。最终我们将创建一个图形:

In [85]:

def show_district_map(col):
    geo_path = 'schools/districts.geojson'
    districts = folium.Map(location=[full['lat'].mean(), full['lon'].mean()], zoom_start=10)
    districts.geo_json(
        geo_path=geo_path,
        data=district_data,
        columns=['school_dist', col],
        key_on='feature.properties.school_dist',
        fill_color='YlGn',
        fill_opacity=0.7,
        line_opacity=0.2,
    )
    districts.save("districts.html")
    return districts

show_district_map("sat_score")

Out[85]:

挖掘注册学生数与SAT分数

现在我们已经依地区画出学校位置和 SAT 成绩确定了上下文,浏览我们分析的人将会对数据的上下文有更好的理解。现在我们已经完成了基础工作,我们可以开始从我们上面寻找关联时所提到的角度分析了。第一个分析角度是学校注册学生人数与 SAT 成绩。

我们可以通过所有学校的注册学生与 SAT 成绩的散点图来分析。

In [87]:

%matplotlib inline

full.plot.scatter(x='total_enrollment', y='sat_score')

Out[87]:

<matplotlib.axes._subplots.AxesSubplot at 0x10fe79978>

如你所见,底下角注册人数较低的部分有个较低 SAT 成绩的聚集。这个集群以外,SAT 成绩与全部注册人数只有轻微正相关。这个画出的关联显示了意想不到的图形.

我们可以通过获取低注册人数且低SAT成绩的学校的名字进行进一步的分析。

In [88]:

full[(full["total_enrollment"] < 1000) & (full["sat_score"] < 1000)]["School Name"]

Out[88]:

34     INTERNATIONAL SCHOOL FOR LIBERAL ARTS
143                                      NaN
148    KINGSBRIDGE INTERNATIONAL HIGH SCHOOL
203                MULTICULTURAL HIGH SCHOOL
294      INTERNATIONAL COMMUNITY HIGH SCHOOL
304          BRONX INTERNATIONAL HIGH SCHOOL
314                                      NaN
317            HIGH SCHOOL OF WORLD CULTURES
320       BROOKLYN INTERNATIONAL HIGH SCHOOL
329    INTERNATIONAL HIGH SCHOOL AT PROSPECT
331               IT TAKES A VILLAGE ACADEMY
351    PAN AMERICAN INTERNATIONAL HIGH SCHOO
Name: School Name, dtype: object

在 Google 上进行了一些搜索确定了这些学校大多数是为了正在学习英语而开设的,所以有这么低注册人数(规模)。这个挖掘向我们展示了并不是所有的注册人数都与 SAT 成绩有关联 - 而是与是否将英语作为第二语言学习的学生有关。

挖掘英语学习者和 SAT 成绩

现在我们知道英语学习者所占学校学生比例与低的 SAT 成绩有关联,我们可以探索其中的规律。ell_percent 列表示一个学校英语学习者所占的比例。我们可以制作关于这个关联的散点图。

In [89]:

full.plot.scatter(x='ell_percent', y='sat_score')

Out[89]:

<matplotlib.axes._subplots.AxesSubplot at 0x10fe824e0>

看起来这里有一组学校有着高的 ell_percentage 值并且有着低的 SAT 成绩。我们可以在学区层面调查这个关系,通过找出每个学区英语学习者所占的比例,并且查看是否与我们的学区层面的 SAT 地图所匹配:

In [90]:

show_district_map("ell_percent")

Out[90]:

我们可通过两个区域层面地图来查看,一个低 ELL(English-language)学习者比例的地区更倾向有高 SAT 成绩,反之亦然。

关联问卷分数和 SAT 分数

学生、家长和老师的问卷结果如果与 SAT 分数有很大的关联的假设是合理的。就例如具有高学术期望的学校倾向于有着更高的 SAT 分数是合理的。为了测这个理论,让我们画出 SAT 分数和多种问卷指标:

In [91]:

full.corr()["sat_score"][["rr_s", "rr_t", "rr_p", "N_s", "N_t", "N_p", "saf_tot_11", "com_tot_11", "aca_tot_11", "eng_tot_11"]].plot.bar()

Out[91]:

<matplotlib.axes._subplots.AxesSubplot at 0x114652400>

惊人的是,关联最大的两个因子是 N_pN_s,它们分别是家长和学生回应的问卷。都与注册人数有着强关联,所以很可能偏离了 ell_learner。此外指标关联最强的就是 saf_t_11,这是学生、家长和老师对学校安全程度的感知。这说明了,越安全的学校,更能让学生在环境里安心学习。然而其它因子,像互动、交流和学术水平都与 SAT 分数无关,这也许表明了纽约在问卷中问了不理想的问题或者想错了因子(如果他们的目的是提高 SAT 分数的话)。

挖掘种族和 SAT 分数

其中一个角度就是调查种族和 SAT 分数的联系。这是一个大相关微分,将其画出来帮助我们理解到底发生了什么:

In [92]:

full.corr()["sat_score"][["white_per", "asian_per", "black_per", "hispanic_per"]].plot.bar()

Out[92]:

<matplotlib.axes._subplots.AxesSubplot at 0x108166ba8>

看起来更高比例的白种和亚洲学生与更高的 SAT 分数有关联,而更高比例的黑人和西班牙裔与更低的 SAT 分数有关联。对于西班牙学生,这可能因为近年的移民还是英语学习者的事实。我们可以标出学区层面的西班牙裔的比例并观察联系。

In [93]:

show_district_map("hispanic_per")

Out[93]:

看起来这里与英语学习者比例有关联,但是有必要对这种和其它种族在 SAT 分数上的差异进行挖掘。

SAT 分数上的性别差异

挖掘性别与 SAT 分数之间的关系是最后一个角度。我们注意更高的女生比例的学校倾向于与更高的 SAT 分数有关联。我们可以可视化为一个条形图:

In [94]:

full.corr()["sat_score"][["male_per", "female_per"]].plot.bar()

Out[94]:

<matplotlib.axes._subplots.AxesSubplot at 0x10774d0f0>

为了挖掘更多的关联性,我们可以制作一个 female_persat_score 的散点图:

In [95]:

full.plot.scatter(x='female_per', y='sat_score')

Out[95]:

<matplotlib.axes._subplots.AxesSubplot at 0x104715160>

看起来这里有一个高女生比例、高 SAT 成绩的簇(右上角)(LCTT 译注:此处散点图并未有如此迹象,可能数据图有误)。我们可以获取簇中学校的名字:

In [96]:

full[(full["female_per"] > 65) & (full["sat_score"] > 1400)]["School Name"]

Out[96]:

3             PROFESSIONAL PERFORMING ARTS HIGH SCH
92                    ELEANOR ROOSEVELT HIGH SCHOOL
100                    TALENT UNLIMITED HIGH SCHOOL
111            FIORELLO H. LAGUARDIA HIGH SCHOOL OF
229                     TOWNSEND HARRIS HIGH SCHOOL
250    FRANK SINATRA SCHOOL OF THE ARTS HIGH SCHOOL
265                  BARD HIGH SCHOOL EARLY COLLEGE
Name: School Name, dtype: object

使用 Google 进行搜索可以知道这些是专注于表演艺术的精英学校。这些学校有着更高比例的女生和更高的 SAT 分数。这可能解释了更高的女生比例和 SAT 分数的关联,并且相反的更高的男生比例与更低的 SAT 分数。

AP 成绩

至今,我们关注的是人口统计角度。还有一个角度是我们通过数据来看参加高阶测试(AP)的学生和 SAT 分数。因为高学术成绩获得者倾向于有着高的 SAT 分数说明了它们是有关联的。

In [98]:

full["ap_avg"] = full["AP Test Takers "] / full["total_enrollment"]

full.plot.scatter(x='ap_avg', y='sat_score')

Out[98]:

<matplotlib.axes._subplots.AxesSubplot at 0x11463a908>

看起来它们之间确实有着很强的关联。有趣的是右上角高 SAT 分数的学校有着高的 AP 测试通过比例:

In [99]:

full[(full["ap_avg"] > .3) & (full["sat_score"] > 1700)]["School Name"]

Out[99]:

92             ELEANOR ROOSEVELT HIGH SCHOOL
98                    STUYVESANT HIGH SCHOOL
157             BRONX HIGH SCHOOL OF SCIENCE
161    HIGH SCHOOL OF AMERICAN STUDIES AT LE
176           BROOKLYN TECHNICAL HIGH SCHOOL
229              TOWNSEND HARRIS HIGH SCHOOL
243    QUEENS HIGH SCHOOL FOR THE SCIENCES A
260      STATEN ISLAND TECHNICAL HIGH SCHOOL
Name: School Name, dtype: object

通过 google 搜索解释了那些大多是高选择性的学校,你需要经过测试才能进入。这就说明了为什么这些学校会有高的 AP 通过人数。

包装故事

在数据科学中,故事不可能真正完结。通过向其他人发布分析,你可以让他们拓展并且运用你的分析到他们所感兴趣的方向。比如在本文中,这里有一些角度我们没有完成,并且可以探索更加深入。

一个开始讲述故事的最好方式就是尝试拓展或者复制别人已经完成的分析。如果你觉得采取这个方式,欢迎你拓展这篇文章的分析,并看看你能发现什么。如果你确实这么做了,请在下面评论,那么我就可以看到了。

下一步

如果你做的足够多,你看起来已经对用数据讲故事和构建你的第一个数据科学作品集有了很好的理解。一旦你完成了你的数据科学工程,发表在 Github 上是一个好的想法,这样别人就能够与你一起合作。

如果你喜欢这篇文章,你可能希望阅读我们‘Build a Data Science Portfolio’系列文章的其它部分:


via: https://www.dataquest.io/blog/data-science-portfolio-project/

作者:Vik Paruchuri 译者:[Yoo-4x] 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Google 的 Grafeas 为容器的元数据提供了一个从镜像、构建细节到安全漏洞的通用 API。

我们运行的软件从来没有比今天更难获得。它分散在本地部署和云服务之间,由不知到有多少的开源组件构建而成,以快速的时间表交付,因此保证安全和质量变成了一个挑战。

最终的结果是软件难以审计、推断、安全化和管理。困难的不只是知道 VM 或容器是用什么构建的, 而是由谁来添加、删除或更改的。Grafeas 最初由 Google 设计,旨在使这些问题更容易解决。

什么是 Grafeas?

Grafeas 是一个定义软件组件的元数据 API 的开源项目。旨在提供一个统一的元数据模式,允许 VM、容器、JAR 文件和其他软件 工件 artifact 描述自己的运行环境以及管理它们的用户。目标是允许像在给定环境中使用的软件一样的审计,以及对该软件所做的更改的审计,并以一致和可靠的方式进行。

Grafeas提供两种格式的元数据 API —— 备注和事件:

  • 备注 note 是有关软件工件的某些方面的细节。可以是已知软件漏洞的描述,有关如何构建软件的详细信息(构建器版本、校验和等),部署历史等。
  • 事件 occurrence 是备注的实例,包含了它们创建的地方和方式的细节。例如,已知软件漏洞的详细信息可能会有描述哪个漏洞扫描程序检测到它的情况、何时被检测到的事件信息,以及该漏洞是否被解决。

备注和事件都存储在仓库中。每个备注和事件都使用标识符进行跟踪,该标识符区分它并使其唯一。

Grafeas 规范包括备注类型的几个基本模式。例如,软件包漏洞模式描述了如何存储 CVE 或漏洞描述的备注信息。现在没有接受新模式类型的正式流程,但是这已经在计划创建这样一个流程。

Grafeas 客户端和第三方支持

现在,Grafeas 主要作为规范和参考形式存在,它在 GitHub 上提供GoPythonJava 的客户端都可以用 Swagger 生成,所以其他语言的客户端也应该不难写出来。

Google 计划让 Grafeas 广泛使用的主要方式是通过 Kubernetes。 Kubernetes 的一个名为 Kritis 的策略引擎,可以根据 Grafeas 元数据对容器采取措施。

除 Google 之外的几家公司已经宣布计划将 Grafeas 的支持添加到现有产品中。例如,CoreOS 正在考察 Grafeas 如何与 Tectonic 集成,Red HatIBM 都计划在其容器产品和服务中添加 Grafeas 集成。


via: https://www.infoworld.com/article/3230462/security/what-is-grafeas-better-auditing-for-containers.html

作者:Serdar Yegulalp 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

rules of coding nasa

引言: 你知道 NASA 顶级程序员如何编写关键任务代码么?为了确保代码更清楚、更安全、且更容易理解,NASA 的喷气推进实验室制定了 10 条编码规则。

NASA 的开发者是编程界最有挑战性的工作之一。他们编写代码并将开发安全的关键任务应用程序作为其主要关注点。

在这种情形下,遵守一些严格的编码规则是重要的。这些规则覆盖软件开发的多个方面,例如软件应该如何编码、应该使用哪些语言特性等。

尽管很难就一个好的编码标准达成共识,NASA 的喷气推进实验室(JPL)遵守一个编码规则,其名为“十的次方:开发安全的关键代码的规则”。

由于 JPL 长期使用 C 语言,这个规则主要是针对于 C 程序语言编写。但是这些规则也可以很容地应用到其它的程序语言。

该规则由 JPL 的首席科学家 Gerard J. Holzmann 制定,这些严格的编码规则主要是聚焦于安全。

NASA 的 10 条编写关键任务代码的规则:

  1. 限制所有代码为极为简单的控制流结构 — 不用 goto 语句、setjmplongjmp 结构,不用间接或直接的递归调用。
  2. 所有循环必须有一个固定的上限值。必须可以被某个检测工具静态证实,该循环不能达到预置的迭代上限值。如果该上限值不能被静态证实,那么可以认为违背该原则。
  3. 在初始化后不要使用动态内存分配。
  4. 如果一个语句一行、一个声明一行的标准格式来参考,那么函数的长度不应该比超过一张纸。通常这意味着每个函数的代码行不能超过 60。
  5. 代码中断言的密度平均低至每个函数 2 个断言。断言被用于检测那些在实际执行中不可能发生的情况。断言必须没有副作用,并应该定义为布尔测试。当一个断言失败时,应该执行一个明确的恢复动作,例如,把错误情况返回给执行该断言失败的函数调用者。对于静态工具来说,任何能被静态工具证实其永远不会失败或永远不能触发的断言违反了该规则(例如,通过增加无用的 assert(true) 语句是不可能满足这个规则的)。
  6. 必须在最小的范围内声明数据对象。
  7. 非 void 函数的返回值在每次函数调用时都必须检查,且在每个函数内其参数的有效性必须进行检查。
  8. 预处理器的使用仅限制于包含头文件和简单的宏定义。符号拼接、可变参数列表(省略号)和递归宏调用都是不允许的。所有的宏必须能够扩展为完整的语法单元。条件编译指令的使用通常是晦涩的,但也不总是能够避免。这意味着即使在一个大的软件开发中超过一两个条件编译指令也要有充足的理由,这超出了避免多次包含头文件的标准做法。每次在代码中这样做的时候必须有基于工具的检查器进行标记,并有充足的理由。
  9. 应该限制指针的使用。特别是不应该有超过一级的解除指针引用。解除指针引用操作不可以隐含在宏定义或类型声明中。还有,不允许使用函数指针。
  10. 从开发的第一天起,必须在编译器开启最高级别警告选项的条件下对代码进行编译。在此设置之下,代码必须零警告编译通过。代码必须利用源代码静态分析工具每天至少检查一次或更多次,且零警告通过。

关于这些规则,NASA 是这么评价的:

这些规则就像汽车中的安全带一样,刚开始你可能感到有一点不适,但是一段时间后就会养成习惯,你会无法想象不使用它们的日子。

此文是否对你有帮助?不要忘了在下面的评论区写下你的反馈。


作者简介:

Adarsh Verma 是 Fossbytes 的共同创始人,他是一个令人尊敬的企业家,他一直对开源、技术突破和完全保持密切关注。可以通过邮件联系他 — [email protected]


via: https://fossbytes.com/nasa-coding-programming-rules-critical/

作者:Adarsh Verma 译者:penghuster 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

云集成高级编排器 Cloud Integrated Advanced Orchestrator (Ciao) 是一个新的负载调度程序,用来解决当前云操作系统项目的局限性。Ciao 提供了一个轻量级,完全基于 TLS 的最小配置。它是 工作量无关的、易于更新、具有优化速度的调度程序,目前已针对 OpenStack 进行了优化。

其设计决策和创新方法在对安全性、可扩展性、可用性和可部署性的要求下进行:

  • 可扩展性: 初始设计目标是伸缩超过 5,000 个节点。因此,调度器架构用新的形式实现:

    • 在 ciao 中,决策制定是去中心化的。它基于拉取模型,允许计算节点从调度代理请求作业。调度程序总能知道启动器的容量,而不要求进行数据更新,并且将调度决策时间保持在最小。启动器异步向调度程序发送容量。
    • 持久化状态跟踪与调度程序决策制定相分离,它让调度程序保持轻量级。这种分离增加了可靠性、可扩展性和性能。结果是调度程序让出了权限并且这不是瓶颈。
  • 可用性: 虚拟机、容器和裸机集成到一个调度器中。所有的负载都被视为平等公民。为了更易于使用,网络通过一个组件间最小化的异步协议进行简化,只需要最少的配置。Ciao 还包括一个新的、简单的 UI。所有的这些功能都集成到一起来简化安装、配置、维护和操作。
  • 轻松部署: 升级应该是预期操作,而不是例外情况。这种新的去中心化状态的体系结构能够无缝升级。为了确保基础设施(例如 OpenStack)始终是最新的,它实现了持续集成/持续交付(CI/CD)模型。Ciao 的设计使得它可以立即杀死任何 Ciao 组件,更换它,并重新启动它,对可用性影响最小。
  • 安全性是必需的: 与调度程序的连接总是加密的:默认情况下 SSL 是打开的,而不是关闭的。加密是从端到端:所有外部连接都需要 HTTPS,组件之间的内部通信是基于 TLS 的。网络支持的一体化保障了租户分离。

初步结果证明是显著的:在 65 秒内启动一万个 Docker 容器和五千个虚拟机。进一步优化还在进行。


via: https://clearlinux.org/ciao

作者:ciao 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

docker

之前的文章中我们提到可以通过容器创建一个我们自定义过的镜像,那么我们是否可以直接通过基础的镜像直接自定义镜像呢?答案当然是可以的,在 Docker 中我们可以从名为 Dockerfile 的文件中读取指令并且自动构建镜像。在本文中,将介绍 Dockerfile 的基本语法以及基本知识。

1、Dockerfile 是什么?

Dockerfile 其实是一份文本文档,里面包含了用户可以用来操作镜像的一些指令。通过顺序执行这些指令,最后得到一个自定义的镜像,这有点类似于我们的 shell 脚本。

2、Dockerfile 示例

接下来先看一个 Dockerfile 示例:

FROM centos
LABEL maintainer="Locez <[email protected]>"
ENV TEST="This is a test env"
COPY nginx.repo /etc/yum.repos.d/nginx.repo
RUN yum update -y && \
        yum install -y nginx
COPY nginx.conf /etc/nginx/nginx.conf
COPY index.html /usr/share/nginx/html/index.html
COPY index_files/ /usr/share/nginx/html/index_files/
EXPOSE 80
CMD ["/usr/sbin/nginx","-g","daemon off;"]

在上面我们可以看到 Dockerfile 中的一些指令,通过名称我们也可以猜到这些指令大概是干嘛的,其中有一些对文件的操作,因此我们先来看看用于存放 Dockerfile 的这个目录的目录结构:

# tree .
.
├── Dockerfile
├── index_files
│   ├── 145049z4og8xyjhx4xy8go.jpg
│   ├── 222746e5vh38d7ey3leyps.jpg
│   ├── 88x31.png
│   ├── archlinux-splash.png
│   ├── bdshare.css
│   ├── Best-Linux-Markdown-Editors.png
│   ├── core.js
│   ├── docker-icon.jpg
│   ├── hadoop-pic1.png
│   ├── jquery_002.js
│   ├── jquery.css
│   ├── jquery.js
│   ├── MathJax.js
│   ├── pic.gif
│   ├── raspberrypiraspberry-pi-logo.jpg
│   ├── script.js
│   ├── scrollup.png
│   ├── share.js
│   ├── style.css
│   └── z_stat.js
├── index.html
├── nginx.conf
└── nginx.repo

1 directory, 24 files

构建镜像

在当前目录下执行以下命令构建镜像:

# docker build -t locez/nginx .
Sending build context to Docker daemon 1.851 MB
Step 1/10 : FROM centos
 ---> 196e0ce0c9fb
Step 2/10 : LABEL maintainer "Locez <[email protected]>"
 ---> Using cache
 ---> 9bba3042bcdb
Step 3/10 : ENV TEST "This is a test env"
 ---> Using cache
 ---> c0ffe95ea0c5
Step 4/10 : COPY nginx.repo /etc/yum.repos.d/nginx.repo
 ---> Using cache
 ---> bb6ee4c30d56
Step 5/10 : RUN yum update -y &&        yum install -y nginx
 ---> Using cache
 ---> 6d46b41099c3
Step 6/10 : COPY nginx.conf /etc/nginx/nginx.conf
 ---> Using cache
 ---> cfe908390aae
Step 7/10 : COPY index.html /usr/share/nginx/html/index.html
 ---> Using cache
 ---> 21729476079d
Step 8/10 : COPY index_files/ /usr/share/nginx/html/index_files/
 ---> Using cache
 ---> 662f06ec7b46
Step 9/10 : EXPOSE 80
 ---> Using cache
 ---> 30db5a889d0a
Step 10/10 : CMD /usr/sbin/nginx -g daemon off;
 ---> Using cache
 ---> d29b9d4036d2
Successfully built d29b9d4036d2

然后用该镜像启动容器:

# docker run -d -it --rm --name test-nginx -p 8080:80 locez/nginx
e06fd991ca1b202e08cf1578f8046355fcbba10dd9a90e11d43282f3a1e36d29

用浏览器访问 http://localhost:8080/ 即可看到部署的内容。

3 Dockerfile 指令解释

Dockerfile 支持 FROMRUNCMDLABELEXPOSEENVADDCOPYENTRYPOINTVOLUMEUSERWORKDIRARGONBUILDSHELL 等指令,这里只选择常用的几个进行讲解,可结合上面的示例进行理解。其它的请自行查阅官方文档。

3.1 FROM

FROM 指令用于指定要操作的基础镜像,因为在我们构建我们自己的镜像的时候需要一个基础镜像。 语法:

FROM <image> [AS <name>]
FROM <image>[:<tag>] [AS <name>]

其中 [AS <name>] 为指定一个名称,在一个 Dockerfile 中多次使用 FROM 时如有需要,可用 COPY --from=<name|index> 语法进行复制。

3.2 RUN

RUN 指令用于执行命令,并且是在新的一层上执行,并把执行后的结果提交,也就是生成新的一层。基于这个问题,我们在使用 RUN 指令时应该尽可能的把要执行的命令一次写完,以减少最后生成的镜像的层数。 语法:

RUN <command>
RUN ["executable", "param1", "param2"]

3.3 CMD

CMD 指令用于给容器启动时指定一个用于执行的命令,例如上例中的 nginx 启动命令。 语法:

CMD ["executable","param1","param2"]
CMD ["param1","param2"] ### 用于给 ENTRYPOINT 指令提供默认参数
CMD command param1 param2

3.4 LABEL

LABEL 指令用于为镜像指定标签,可用 docker inspect 命令查看。可用来代替被舍弃的 MAINTAINER 命令。 语法:

LABEL <key>=<value> <key>=<value> <key>=<value> ...

3.5 EXPOSE

EXPOSE 指令用于告诉 Docker 容器监听的特殊端口,但是此时端口还没有暴露给 host ,只有当在运行一个容器显式用参数 -p 或者 -P 的时候才会暴露端口。 语法:

EXPOSE <port> [<port>/<protocol>...]

3.6 ENV

ENV 指令用于设定环境变量。 语法:

ENV <key> <value>
ENV <key>=<value> ...

3.7 ADD

ADD 指令用于复制新文件,目录,远程文件到容器中。其中 <src> 可以为文件,目录,URL,若为可解压文件,在复制后会解压。 语法:

ADD <src>... <dest>
ADD ["<src>",... "<dest>"]

3.8 COPY

COPY 指令与 ADD 指令非常相似,但 COPY 比较直观且简单,它只支持本地的文件以及目录的复制,不像 ADD 指令可以远程获取文件并解压。 语法:

COPY <src>... <dest>
COPY ["<src>",... "<dest>"]

3.9 ENTRYPOINT

ENTRYPOINT 指令也跟 CMD 指令相似,用于指定容器启动时执行的命令。当使用 ENTRYPOINT 指令时,可用 CMD 命令配合,这样在启动容器时,可以对 CMD 指令写入的参数进行覆盖。 语法:

ENTRYPOINT ["executable", "param1", "param2"]

例子:

ENTRYPOINT ["top","-b"]
CMD ["-c"]

上面的 -c 参数可以在启动时覆盖 docker run -it --rm --name test top -H。 如果要覆盖 ENTRYPOINT 指令则用 --entrypoint 参数启动容器。

3.10 VOLUME

VOLUME 指令用于为容器创建一个挂载点,这个挂载点可以用来挂载 本地文件/文件夹 也可以用来挂载 数据卷。其中若在启动一个新容器时没有指定挂载目录,则会自动创建一个数据卷,当容器被销毁时,数据卷如果没有被其它容器引用则会被删除。 语法:

VOLUME ["/data1","/data2"]

3.11 USER

USER 指令用于设置执行 RUN, CMD, ENTRYPOINT 等指令的用户以及用户组。默认为 root 用户。 语法:

USER <user>[:<group>]

3.12 WORKDIR

WORKDIR 指令用于设置 RUN, CMD, ENTRYPOINT, COPY, ADD 等指令的工作目录。 语法:

WORKDIR /path/to/workdir

4 总结


本文从一个具体的例子出发,讲述了如何利用 Dockerfile 构建镜像,然后解释了 Dockerfile 文件中的指令的语法,有关更多内容可访问官方文档。

5 参考资料


配置是成功安装 NixOS 的关键。

我用 Linux 有些年头了。在这些年里我很有幸见证了开源的发展。各色各样的发行版在安装方面的努力,也是其中的一个比较独特的部分。以前,安装 Linux 是个最好让有技术的人来干的任务。现在,只要你会装软件,你就会安装 Linux。简单,并且,不是我吹,在吸引新用户方面效果拔群。事实上安装整个 Linux 操作系统都要比 Windows 用户安装个更新看起来要快一点。

但每一次,我都喜欢看到一些不同的东西——那些可以让我体验新鲜的东西。NixOS 在这方面就做的别具一格。讲真,我原来也就把它当作另一个提供标准特性和 KDE Plasma 5 界面的 Linux 发行版。

好像也没什么不对。

下载 ISO 映像后,我启动了 VirtualBox 并用下载的镜像创建了个新的虚拟机。VM 启动后,出来的是 Bash 的登录界面,界面上指导我用空密码去登录 root 账号,以及我该如何启动 GUI 显示管理器(图 1)。

 title=

图 1: 与 NixOS 的初次接触可能不是太和谐。

“好吧”我这样想着,“打开看看吧!”

GUI 启动和运行时(KDE Plasma 5),我没找到喜闻乐见的“安装”按钮。原来,NixOS 是一个在安装前需要你配置的发行版,真有趣。那就让我们瞧瞧它是如何做到的吧!

安装前配置

你需要做的第一件事是建分区。由于 NixOS 安装程序不包含分区工具,你得用自带的 GParted (图 2)来创建一个 EXT4 分区。

 title=

图 2: 安装前对磁盘分区。

创建好分区,然后用命令 mount /dev/sdX /mnt 挂载。(请自行替换 sdX 为你新创建的分区)。

你现在需要创建一个配置文件。命令如下:

nixos-generate-config --root /mnt

上面的命令会创建两个文件(存放在目录 /mnt/etc/nixos 中):

  • configuration.nix — 默认配置文件。
  • hardware-configuration.nix — 硬件配置(无法编辑)

通过命令 nano /mnt/etc/nixos/configuration.nix 打开文件。其中有一些需要编辑的地方得注意。第一个改动便是设置启动选项。找到行:

# boot.loader.grub.device = "/dev/sda"; # 或 efi 时用 "nodev"

删除行首的 # 使该选项生效(确保 /dev/sda 与你新建的分区)。

通过配置文件,你可以设置时区和追加要安装的软件包。来看一个被注释掉的安装包的示例:

# List packages installed in system profile. To search by name, run:
# nix-env -aqP | grep wget
# environment.systemPackages = with pkgs; [
#     wget vim
# ];

如果你想要添加软件包,并在安装时安装它们,那就取消掉这段注释,并添加你需要的软件包。举个例子,比方说你要把 LibreOffice 加进去。示例详见下方:

# List packages installed in system profile. To search by name, run:
nix-env -aqP | grep wget
environment.systemPackages = with pkgs; [
    libreoffice wget vim
];

你可以通过输入命令 nix-env -aqP | grep PACKAGENAME 来寻找确切的包名(PACKAGENAME 为你想要找的软件包)。如果你不想输命令,你也可以检索 NixOS 的软件包数据库

在你把所有的软件包都添加完后,你还有件事儿需要做(如果你想要登录到桌面的话,我觉得你还得折腾下 KDE Plasma 5 桌面)。翻到配置文件的末尾并在最后的 } 符号前,追加如下内容:

services.xserver = {
    enable = true;
    displayManager.sddm.enable = true;
    desktopManager.plasma5.enable = true;
};

NixOS 官方文件 中,你能找到配置文件中更多的选项。保存并关掉配置文件。

安装

在你按照自己的需求完善好配置之后,使用命令(需要 root 权限) nixos-install。完成安装所需要的时间,会随着你加入的软件包多少有所区别。安装结束后,你可以使用命令重启系统,(重启之后)迎接你的就是 KDE Plasma 5 的登录管理界面了(图 3)。

 title=

图 3: KDE Plasma 5 登录管理界面

安装后

你要首先要做的两件事之一便是给 root 用户设个密码(通过输入命令 passwd 来修改默认的密码),以及添加一个标准用户。做法和其它的 Linux 发行版无二。用 root 用户登录,然后在终端输入命令:

useradd -m USER

USER 替换成你想要添加的用户名。然后通过下面的命令给用户设上密码:

passwd USER

同样的将 USER 替换成你添加的用户。

然后会有提示引导你填写并验证新密码。然后,你就能用标准用户登录 NixOS 啦。

NixOS 在你安装并运行后,你可以为系统添加新的软件包,但并非通过寻常的方式。如果你发现你需要安装些新东西,你得回到配置文件(位置就是 /etc/nixos/ ),找到之前安装时添加软件包的位置,运行以下命令(需要 root 权限):

nixos-rebuild switch

命令执行结束后,你就能使用新安装的软件包了。

Enjoy NixOS

现在,NixOS 已经带着所有你想安装的软件和 KDE Plasma 5 桌面运行起来了。要知道,你所做的不仅仅只是安装了个 Linux 发行版,关键是你自定义出来的发行版非常符合你的需求。所以好好享受你的 NixOS 吧!


via: https://www.linux.com/learn/intro-to-linux/2017/10/nixos-linux-lets-you-configure-your-os-installing

作者:JACK WALLEN 译者:martin2011qi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出