100% found this document useful (5 votes)
29 views

Instant Access to Clojure Data Analysis Cookbook 2nd Edition Edition Eric Rochester ebook Full Chapters

Analysis

Uploaded by

rangiecyntie
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (5 votes)
29 views

Instant Access to Clojure Data Analysis Cookbook 2nd Edition Edition Eric Rochester ebook Full Chapters

Analysis

Uploaded by

rangiecyntie
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 81

Visit https://ebookgate.

com to download the full version and


explore more ebooks

Clojure Data Analysis Cookbook 2nd Edition Edition


Eric Rochester

_____ Click the link below to download _____


https://ebookgate.com/product/clojure-data-analysis-
cookbook-2nd-edition-edition-eric-rochester/

Explore and download more ebooks at ebookgate.com


Here are some recommended products that might interest you.
You can download now and explore!

Scala Data Analysis Cookbook Navigate the world of data


analysis visualization and machine learning with over 100
hands on Scala recipes 1st Edition Arun Manivannan
https://ebookgate.com/product/scala-data-analysis-cookbook-navigate-
the-world-of-data-analysis-visualization-and-machine-learning-with-
over-100-hands-on-scala-recipes-1st-edition-arun-manivannan/
ebookgate.com

Analysis of Economic Data 2nd Edition Gary Koop

https://ebookgate.com/product/analysis-of-economic-data-2nd-edition-
gary-koop/

ebookgate.com

Data Collection and Analysis 2nd Edition Roger Sapsford

https://ebookgate.com/product/data-collection-and-analysis-2nd-
edition-roger-sapsford/

ebookgate.com

Data Analysis for Physical Scientists Featuring Excel 2nd


Edition Les Kirkup

https://ebookgate.com/product/data-analysis-for-physical-scientists-
featuring-excel-2nd-edition-les-kirkup/

ebookgate.com
Statistics and Data Analysis for Nursing Research 2nd
Edition Denise Polit

https://ebookgate.com/product/statistics-and-data-analysis-for-
nursing-research-2nd-edition-denise-polit/

ebookgate.com

The Joy of Clojure Thinking the Clojure Way 1st Edition


Michael Fogus

https://ebookgate.com/product/the-joy-of-clojure-thinking-the-clojure-
way-1st-edition-michael-fogus/

ebookgate.com

HTML5 Graphing and Data Visualization Cookbook 1st Edition


Ben Fhala

https://ebookgate.com/product/html5-graphing-and-data-visualization-
cookbook-1st-edition-ben-fhala/

ebookgate.com

Categorical Data Analysis Using the SAS System 2nd Edition


Maura E. Stokes

https://ebookgate.com/product/categorical-data-analysis-using-the-sas-
system-2nd-edition-maura-e-stokes/

ebookgate.com

Microarrays Volume 2 Applications and Data Analysis 2nd


Edition Conor W. Sipe

https://ebookgate.com/product/microarrays-volume-2-applications-and-
data-analysis-2nd-edition-conor-w-sipe/

ebookgate.com
Clojure Data Analysis
Cookbook
Second Edition

Dive into data analysis with Clojure through over 100


practical recipes for every stage of the analysis and
collection process

Eric Rochester

BIRMINGHAM - MUMBAI
Clojure Data Analysis Cookbook
Second Edition

Copyright © 2015 Packt Publishing

All rights reserved. No part of this book may be reproduced, stored in a retrieval system,
or transmitted in any form or by any means, without the prior written permission of the
publisher, except in the case of brief quotations embedded in critical articles or reviews.

Every effort has been made in the preparation of this book to ensure the accuracy of the
information presented. However, the information contained in this book is sold without
warranty, either express or implied. Neither the author, nor Packt Publishing, and its dealers
and distributors will be held liable for any damages caused or alleged to be caused directly
or indirectly by this book.

Packt Publishing has endeavored to provide trademark information about all of the
companies and products mentioned in this book by the appropriate use of capitals.
However, Packt Publishing cannot guarantee the accuracy of this information.

First published: March 2013

Second edition: January 2015

Production reference: 1220115

Published by Packt Publishing Ltd.


Livery Place
35 Livery Street
Birmingham B3 2PB, UK.

ISBN 978-1-78439-029-7

www.packtpub.com
Credits

Author Project Coordinator


Eric Rochester Neha Thakur

Reviewers Proofreaders
Vitomir Kovanovic Ameesha Green
Muktabh Mayank Srivastava Joel T. Johnson
Federico Tomassetti Samantha Lyon

Commissioning Editor Indexer


Ashwin Nair Priya Sane

Acquisition Editor Graphics


Sam Wood Sheetal Aute
Disha Haria
Content Development Editor
Parita Khedekar Production Coordinator
Nitesh Thakur
Technical Editor
Ryan Kochery Cover Work
Nitesh Thakur
Copy Editors
Dipti Kapadia
Puja Lalwani
Vikrant Phadke
About the Author

Eric Rochester enjoys reading, writing, and spending time with his wife and kids. When
he’s not doing these things, he programs in a variety of languages and platforms, including
websites and systems in Python, and libraries for linguistics and statistics in C#. Currently,
he is exploring functional programming languages, including Clojure and Haskell. He works
at Scholars’ Lab in the library at the University of Virginia, helping humanities professors and
graduate students realize their digitally informed research agendas. He is also the author of
Mastering Clojure Data Analysis, Packt Publishing.

I’d like to thank everyone. My technical reviewers proved invaluable.


Also, thank you to the editorial staff at Packt Publishing. This book is
much stronger because of all of their feedback, and any remaining
deficiencies are mine alone.

A special thanks to Jackie, Melina, and Micah. They’ve been patient and
supportive while I worked on this project. It is, in every way, for them.
About the Reviewers

Vitomir Kovanovic is a PhD student at the School of Informatics, University of Edinburgh,


Edinburgh, UK. He received an MSc degree in computer science and software engineering
in 2011, and BSc in information systems and business administration in 2009 from the
University of Belgrade, Serbia. His research interests include learning analytics, educational
data mining, and online education. He is a member of the Society for Learning Analytics
Research and a member of program committees of several conferences and journals in
technology-enhanced learning. In his PhD research, he focuses on the use of trace data for
understanding the effects of technology use on the quality of the social learning process and
learning outcomes. For more information, visit http://vitomir.kovanovic.info/

Muktabh Mayank Srivastava is a data scientist and the cofounder of ParallelDots.com.


Previously, he helped in solving many complex data analysis and machine learning problems
for clients from different domains such as healthcare, retail, procurement, automation,
Bitcoin, social recommendation engines, geolocation fact-finding, customer profiling,
and so on.

His new venture is ParallelDots. It is a tool that allows any content archive to be presented
in a story using advanced techniques of NLP and machine learning. For publishers and
bloggers, it automatically creates a timeline of any event using their archive and presents
it in an interactive, intuitive, and easy-to-navigate interface on their webpage. You can find
him on LinkedIn at http://in.linkedin.com/in/muktabh/ and on Twitter at
@muktabh / @ParallelDots.
Federico Tomassetti has been programming since he was a child and has a PhD
in software engineering. He works as a consultant on model-driven development and
domain-specific languages, writes technical articles, teaches programming, and works as
a full-stack software engineer.

He has experience working in Italy, Germany, and Ireland, and he is currently working
at Groupon International.

You can read about his projects on http://federico-tomassetti.it/ or


https://github.com/ftomassetti/.
www.PacktPub.com

Support files, eBooks, discount offers, and more


For support files and downloads related to your book, please visit www.PacktPub.com.

Did you know that Packt offers eBook versions of every book published, with PDF and ePub
files available? You can upgrade to the eBook version at www.PacktPub.com and as a print
book customer, you are entitled to a discount on the eBook copy. Get in touch with us at
[email protected] for more details.

At www.PacktPub.com, you can also read a collection of free technical articles, sign up
for a range of free newsletters and receive exclusive discounts and offers on Packt books
and eBooks.
TM

https://www2.packtpub.com/books/subscription/packtlib

Do you need instant solutions to your IT questions? PacktLib is Packt’s online digital book
library. Here, you can search, access, and read Packt’s entire library of books.

Why subscribe?
ff Fully searchable across every book published by Packt
ff Copy and paste, print, and bookmark content
ff On demand and accessible via a web browser

Free access for Packt account holders


If you have an account with Packt at www.PacktPub.com, you can use this to access
PacktLib today and view 9 entirely free books. Simply use your login credentials for
immediate access.
Table of Contents
Preface 1
Chapter 1: Importing Data for Analysis 7
Introduction 7
Creating a new project 8
Reading CSV data into Incanter datasets 9
Reading JSON data into Incanter datasets 12
Reading data from Excel with Incanter 14
Reading data from JDBC databases 15
Reading XML data into Incanter datasets 18
Scraping data from tables in web pages 21
Scraping textual data from web pages 25
Reading RDF data 29
Querying RDF data with SPARQL 33
Aggregating data from different formats 38
Chapter 2: Cleaning and Validating Data 45
Introduction 45
Cleaning data with regular expressions 46
Maintaining consistency with synonym maps 48
Identifying and removing duplicate data 50
Regularizing numbers 53
Calculating relative values 55
Parsing dates and times 57
Lazily processing very large data sets 59
Sampling from very large data sets 61
Fixing spelling errors 64
Parsing custom data formats 68
Validating data with Valip 70
Table of Contents

Chapter 3: Managing Complexity with Concurrent Programming 73


Introduction 74
Managing program complexity with STM 75
Managing program complexity with agents 79
Getting better performance with commute 82
Combining agents and STM 83
Maintaining consistency with ensure 85
Introducing safe side effects into the STM 88
Maintaining data consistency with validators 91
Monitoring processing with watchers 94
Debugging concurrent programs with watchers 96
Recovering from errors in agents 98
Managing large inputs with sized queues 100
Chapter 4: Improving Performance with Parallel Programming 101
Introduction 102
Parallelizing processing with pmap 102
Parallelizing processing with Incanter 106
Partitioning Monte Carlo simulations for better pmap performance 107
Finding the optimal partition size with simulated annealing 112
Combining function calls with reducers 116
Parallelizing with reducers 118
Generating online summary statistics for data streams with reducers 121
Using type hints 124
Benchmarking with Criterium 127
Chapter 5: Distributed Data Processing with Cascalog 131
Introduction 131
Initializing Cascalog and Hadoop for distributed processing 133
Querying data with Cascalog 137
Distributing data with Apache HDFS 138
Parsing CSV files with Cascalog 141
Executing complex queries with Cascalog 143
Aggregating data with Cascalog 146
Defining new Cascalog operators 148
Composing Cascalog queries 151
Transforming data with Cascalog 153

ii
Table of Contents

Chapter 6: Working with Incanter Datasets 155


Introduction 156
Loading Incanter's sample datasets 156
Loading Clojure data structures into datasets 157
Viewing datasets interactively with view 159
Converting datasets to matrices 161
Using infix formulas in Incanter 163
Selecting columns with $ 165
Selecting rows with $ 167
Filtering datasets with $where 169
Grouping data with $group-by 170
Saving datasets to CSV and JSON 172
Projecting from multiple datasets with $join 173
Chapter 7: Statistical Data Analysis with Incanter 177
Introduction 177
Generating summary statistics with $rollup 178
Working with changes in values 180
Scaling variables to simplify variable relationships 182
Working with time series data with Incanter Zoo 184
Smoothing variables to decrease variation 186
Validating sample statistics with bootstrapping 189
Modeling linear relationships 192
Modeling non-linear relationships 195
Modeling multinomial Bayesian distributions 199
Finding data errors with Benford's law 202
Chapter 8: Working with Mathematica and R 207
Introduction 207
Setting up Mathematica to talk to Clojuratica for Mac OS X and Linux 208
Setting up Mathematica to talk to Clojuratica for Windows 212
Calling Mathematica functions from Clojuratica 214
Sending matrixes to Mathematica from Clojuratica 215
Evaluating Mathematica scripts from Clojuratica 217
Creating functions from Mathematica 218
Setting up R to talk to Clojure 219
Calling R functions from Clojure 221
Passing vectors into R 222
Evaluating R files from Clojure 224
Plotting in R from Clojure 226

iii
Table of Contents

Chapter 9: Clustering, Classifying, and Working with Weka 229


Introduction 229
Loading CSV and ARFF files into Weka 230
Filtering, renaming, and deleting columns in Weka datasets 232
Discovering groups of data using K-Means clustering 235
Finding hierarchical clusters in Weka 241
Clustering with SOMs in Incanter 244
Classifying data with decision trees 246
Classifying data with the Naive Bayesian classifier 249
Classifying data with support vector machines 251
Finding associations in data with the Apriori algorithm 254
Chapter 10: Working with Unstructured and Textual Data 257
Introduction 258
Tokenizing text 258
Finding sentences 259
Focusing on content words with stoplists 260
Getting document frequencies 262
Scaling document frequencies by document size 264
Scaling document frequencies with TF-IDF 266
Finding people, places, and things with Named Entity Recognition 270
Mapping documents to a sparse vector space representation 272
Performing topic modeling with MALLET 274
Performing naïve Bayesian classification with MALLET 277
Chapter 11: Graphing in Incanter 281
Introduction 281
Creating scatter plots with Incanter 282
Graphing non-numeric data in bar charts 284
Creating histograms with Incanter 287
Creating function plots with Incanter 288
Adding equations to Incanter charts 290
Adding lines to scatter charts 292
Customizing charts with JFreeChart 293
Customizing chart colors and styles 296
Saving Incanter graphs to PNG 298
Using PCA to graph multi-dimensional data 299
Creating dynamic charts with Incanter 302

iv
Table of Contents

Chapter 12: Creating Charts for the Web 305


Introduction 305
Serving data with Ring and Compojure 306
Creating HTML with Hiccup 311
Setting up to use ClojureScript 313
Creating scatter plots with NVD3 317
Creating bar charts with NVD3 323
Creating histograms with NVD3 326
Creating time series charts with D3 329
Visualizing graphs with force-directed layouts 334
Creating interactive visualizations with D3 339
Index 345

v
Preface
Welcome to the second edition of Clojure Data Analysis Cookbook! It seems that books
become obsolete almost as quickly as software does, so here we have the opportunity to
keep things up-to-date and useful.

Moreover, the state of the art of data analysis is also still evolving and changing. The
techniques and technologies are being refined and improved. Hopefully, this book will capture
some of that. I've also added a new chapter on how to work with unstructured textual data.

In spite of these changes, some things have stayed the same. Clojure has further proven
itself to be an excellent environment to work with data. As a member of the lisp family of
languages, it inherits a flexibility and power that is hard to match. The concurrency and
parallelization features have further proven themselves as great tools for developing
software and analyzing data.

Clojure's usefulness for data analysis is further improved by a number of strong libraries.
Incanter provides a practical environment to work with data and perform statistical analysis.
Cascalog is an easy-to-use wrapper over Hadoop and Cascading. Finally, when you're ready
to publish your results, ClojureScript, an implementation of Clojure that generates JavaScript,
can help you to visualize your data in an effective and persuasive way.

Moreover, Clojure runs on the Java Virtual Machine (JVM), so any libraries written for Java are
available too. This gives Clojure an incredible amount of breadth and power.

I hope that this book will give you the tools and techniques you need to get answers from
your data.
Preface

What this book covers


Chapter 1, Importing Data for Analysis, covers how to read data from a variety of sources,
including CSV files, web pages, and linked semantic web data.

Chapter 2, Cleaning and Validating Data, presents strategies and implementations to


normalize dates, fix spelling, and work with large datasets. Getting data into a useable shape
is an important, but often overlooked, stage of data analysis.

Chapter 3, Managing Complexity with Concurrent Programming, covers Clojure's concurrency


features and how you can use them to simplify your programs.

Chapter 4, Improving Performance with Parallel Programming, covers how to use Clojure's
parallel processing capabilities to speed up the processing of data.

Chapter 5, Distributed Data Processing with Cascalog, covers how to use Cascalog as a
wrapper over Hadoop and the Cascading library to process large amounts of data distributed
over multiple computers.

Chapter 6, Working with Incanter Datasets, covers the basics of working with Incanter
datasets. Datasets are the core data structures used by Incanter, and understanding them is
necessary in order to use Incanter effectively.

Chapter 7, Statistical Data Analysis with Incanter, covers a variety of statistical processes and
tests used in data analysis. Some of these are quite simple, such as generating summary
statistics. Others are more complex, such as performing linear regressions and auditing data
with Benford's Law.

Chapter 8, Working with Mathematica and R, talks about how to set up Clojure in order to talk
to Mathematica or R. These are powerful data analysis systems, and we might want to use
them sometimes. This chapter will show you how to get these systems to work together, as
well as some tasks that you can perform once they are communicating.

Chapter 9, Clustering, Classifying, and Working with Weka, covers more advanced machine
learning techniques. In this chapter, we'll primarily use the Weka machine learning library.
Some recipes will discuss how to use it and the data structures its built on, while other recipes
will demonstrate machine learning algorithms.

Chapter 10, Working with Unstructured and Textual Data, looks at tools and techniques used
to extract information from the reams of unstructured, textual data.

Chapter 11, Graphing in Incanter, shows you how to generate graphs and other visualizations
in Incanter. These can be important for exploring and learning about your data and also for
publishing and presenting your results.

Chapter 12, Creating Charts for the Web, shows you how to set up a simple web application in
order to present findings from data analysis. It will include a number of recipes that leverage
the powerful D3 visualization library.
2
Preface

What you need for this book


One piece of software required for this book is the Java Development Kit (JDK), which you
can obtain from http://www.oracle.com/technetwork/java/javase/downloads/
index.html. JDK is necessary to run and develop on the Java platform.

The other major piece of software that you'll need is Leiningen 2, which you can download
and install from http://leiningen.org/. Leiningen 2 is a tool used to manage Clojure
projects and their dependencies. It has become the de facto standard project tool in the
Clojure community.

Throughout this book, we'll use a number of other Clojure and Java libraries, including Clojure
itself. Leiningen will take care of downloading these for us as we need them.

You'll also need a text editor or Integrated Development Environment (IDE). If you already have
a text editor of your choice, you can probably use it. See http://clojure.org/getting_
started for tips and plugins for using your particular favorite environment. If you don't have a
preference, I'd suggest that you take a look at using Eclipse with Counterclockwise. There are
instructions to this set up at https://code.google.com/p/counterclockwise/.

That is all that's required. However, at various places throughout the book, some recipes will
access other software. The recipes in Chapter 8, Working with Mathematica and R, that are
related to Mathematica will require Mathematica, obviously, and those that are related to R
will require that. However, these programs won't be used in the rest of the book, and whether
you're interested in those recipes might depend on whether you already have this software.

Who this book is for


This book is for programmers or data scientists who are familiar with Clojure and want to use
it in their data analysis processes. This isn't a tutorial on Clojure—there are already a number
of excellent introductory books out there—so you'll need to be familiar with the language,
but you don't need to be an expert.

Likewise, you don't have to be an expert on data analysis, although you should probably be
familiar with its tasks, processes, and techniques. While you might be able to glean enough
from these recipes to get started with, for it to be truly effective, you'll want to get a more
thorough introduction to this field.

3
Preface

Conventions
In this book, you will find a number of styles of text that distinguish between different kinds of
information. Here are some examples of these styles, and an explanation of their meaning.

Code words in text, database table names, folder names, filenames, file extensions,
pathnames, dummy URLs, user input, and Twitter handles are shown as follows: "Now, there
will be a new subdirectory named getting-data.

A block of code is set as follows:


(defproject getting-data "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.6.0"]])

When we wish to draw your attention to a particular part of a code block, the relevant lines or
items are set in bold:
(defn watch-debugging
[input-file]
(let [reader (agent
(seque
(mapcat
lazy-read-csv
input-files)))
caster (agent nil)
sink (agent [])
counter (ref 0)
done (ref false)]
(add-watch caster :counter
(partial watch-caster counter))
(add-watch caster :debug debug-watch)
(send reader read-row caster sink done)
(wait-for-it 250 done)
{:results @sink
:count-watcher @counter}))

Any command-line input or output is written as follows:


$ lein new getting-data
Generating a project called getting-data based on the default template.
To see other templates (app, lein plugin, etc), try lein help new.

4
Preface

New terms and important words are shown in bold. Words that you see on the screen,
in menus or dialog boxes for example, appear in the text like this: "Take a look at the
Hadoop website for the Getting Started documentation of your version. Get a single
node setup working".

Warnings or important notes appear in a box like this.

Tips and tricks appear like this.

Reader feedback
Feedback from our readers is always welcome. Let us know what you think about this
book—what you liked or may have disliked. Reader feedback is important for us to develop
titles that you really get the most out of.

To send us general feedback, simply send an e-mail to [email protected], and


mention the book title via the subject of your message.

If there is a topic that you have expertise in and you are interested in either writing or
contributing to a book, see our author guide on www.packtpub.com/authors.

Customer support
Now that you are the proud owner of a Packt book, we have a number of things to help you to
get the most from your purchase.

Downloading the example code


You can download the example code files for all Packt books you have purchased from
your account at http://www.packtpub.com. If you purchased this book elsewhere,
you can visit http://www.packtpub.com/support and register to have the files
e-mailed directly to you.

5
Preface

Downloading the color images of this book


We also provide you a PDF file that has color images of the screenshots/diagrams used in
this book. The color images will help you better understand the changes in the output. You
can download this file from: https://www.packtpub.com/sites/default/files/
downloads/B03480_coloredimages.pdf.

Errata
Although we have taken every care to ensure the accuracy of our content, mistakes do happen.
If you find a mistake in one of our books—maybe a mistake in the text or the code—we would be
grateful if you could report this to us. By doing so, you can save other readers from frustration
and help us improve subsequent versions of this book. If you find any errata, please report them
by visiting http://www.packtpub.com/submit-errata, selecting your book, clicking on
the Errata Submission Form link, and entering the details of your errata. Once your errata are
verified, your submission will be accepted and the errata will be uploaded to our website or
added to any list of existing errata under the Errata section of that title.

To view the previously submitted errata, go to https://www.packtpub.com/books/


content/support and enter the name of the book in the search field. The required
information will appear under the Errata section.

Piracy
Piracy of copyright material on the Internet is an ongoing problem across all media. At Packt,
we take the protection of our copyright and licenses very seriously. If you come across any
illegal copies of our works, in any form, on the Internet, please provide us with the location
address or website name immediately so that we can pursue a remedy.

Please contact us at [email protected] with a link to the suspected


pirated material.

We appreciate your help in protecting our authors, and our ability to bring you
valuable content.

Questions
You can contact us at [email protected] if you are having a problem with any
aspect of the book, and we will do our best to address it.

6
Importing Data for
1
Analysis
In this chapter, we will cover the following recipes:

ff Creating a new project


ff Reading CSV data into Incanter datasets
ff Reading JSON data into Incanter datasets
ff Reading data from Excel with Incanter
ff Reading data from JDBC databases
ff Reading XML data into Incanter datasets
ff Scraping data from tables in web pages
ff Scraping textual data from web pages
ff Reading RDF data
ff Querying RDF data with SPARQL
ff Aggregating data from different formats

Introduction
There's not much data analysis that can be done without data, so the first step in any project
is to evaluate the data we have and the data that we need. Once we have some idea of what
we'll need, we have to figure out how to get it.
Importing Data for Analysis

Many of the recipes in this chapter and in this book use Incanter (http://incanter.org/)
to import the data and target Incanter datasets. Incanter is a library that is used for statistical
analysis and graphics in Clojure (similar to R) an open source language for statistical
computing (http://www.r-project.org/). Incanter might not be suitable for every task
(for example, we'll use the Weka library for machine learning later) but it is still an important
part of our toolkit for doing data analysis in Clojure. This chapter has a collection of recipes
that can be used to gather data and make it accessible to Clojure.

For the very first recipe, we'll take a look at how to start a new project. We'll start with very
simple formats such as comma-separated values (CSV) and move into reading data from
relational databases using JDBC. We'll examine more complicated data sources, such as
web scraping and linked data (RDF).

Creating a new project


Over the course of this book, we're going to use a number of third-party libraries and external
dependencies. We will need a tool to download them and track them. We also need a tool to
set up the environment and start a REPL (read-eval-print-loop or interactive interpreter) that
can access our code or to execute our program. REPLs allow you to program interactively. It's a
great environment for exploratory programming, irrespective of whether that means exploring
library APIs or exploring data.

We'll use Leiningen for this (http://leiningen.org/). This has become a standard
package automation and management system.

Getting ready
Visit the Leiningen site and download the lein script. This will download the Leiningen JAR
file when it's needed. The instructions are clear, and it's a simple process.

How to do it...
To generate a new project, use the lein new command, passing the name of the project
to it:
$ lein new getting-data
Generating a project called getting-data based on the default template.
To see other templates (app, lein plugin, etc), try lein help new.

There will be a new subdirectory named getting-data. It will contain files with stubs for the
getting-data.core namespace and for tests.

8
Chapter 1

How it works...
The new project directory also contains a file named project.clj. This file contains
metadata about the project, such as its name, version, license, and more. It also contains
a list of the dependencies that our code will use, as shown in the following snippet. The
specifications that this file uses allow it to search Maven repositories and directories of
Clojure libraries (Clojars, https://clojars.org/) in order to download the project's
dependencies. Thus, it integrates well with Java's own packaging system as developed with
Maven (http://maven.apache.org/).
(defproject getting-data "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.6.0"]])

In the Getting ready section of each recipe, we'll see the libraries that we need to list in the
:dependencies section of this file. Then, when you run any lein command, it will download
the dependencies first.

Reading CSV data into Incanter datasets


One of the simplest data formats is comma-separated values (CSV), and you'll find that
it's everywhere. Excel reads and writes CSV directly, as do most databases. Also, because
it's really just plain text, it's easy to generate CSV files or to access them from any
programming language.

Getting ready
First, let's make sure that we have the correct libraries loaded. Here's how the project
Leiningen (https://github.com/technomancy/leiningen) project.clj file should
look (although you might be able to use more up-to-date versions of the dependencies):
(defproject getting-data "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.6.0"]
[incanter "1.5.5"]])

Downloading the example code


You can download the example code files for all Packt books you have
purchased from your account at http://www.packtpub.com. If you
purchased this book elsewhere, you can visit http://www.packtpub.
com/support and register to have the files e-mailed directly to you.

9
Importing Data for Analysis

Also, in your REPL or your file, include these lines:


(use 'incanter.core
'incanter.io)

Finally, downloaded a list of rest area locations from POI Factory at http://www.poi-
factory.com/node/6643. The data is in a file named data/RestAreasCombined(Ver.
BN).csv. The version designation might be different though, as the file is updated. You'll also
need to register on the site in order to download the data. The file contains this data, which is
the location and description of the rest stops along the highway:
-67.834062,46.141129,"REST AREA-FOLLOW SIGNS SB I-95 MM305","RR, PT,
Pets, HF"
-67.845906,46.138084,"REST AREA-FOLLOW SIGNS NB I-95 MM305","RR, PT,
Pets, HF"
-68.498471,45.659781,"TURNOUT NB I-95 MM249","Scenic Vista-NO
FACILITIES"
-68.534061,45.598464,"REST AREA SB I-95 MM240","RR, PT, Pets, HF"

In the project directory, we have to create a subdirectory named data and place the file in
this subdirectory.

I also created a copy of this file with a row listing the names of the columns and named it
RestAreasCombined(Ver.BN)-headers.csv.

How to do it…
1. Now, use the incanter.io/read-dataset function in your REPL:
user=> (read-dataset "data/RestAreasCombined(Ver.BJ).csv")

| :col0 | :col1 | :col2


| :col3 |
|------------+-----------+--------------------------------------+-
---------------------------|
| -67.834062 | 46.141129 | REST AREA-FOLLOW SIGNS SB I-95 MM305 |
RR, PT, Pets, HF |
| -67.845906 | 46.138084 | REST AREA-FOLLOW SIGNS NB I-95 MM305 |
RR, PT, Pets, HF |
| -68.498471 | 45.659781 | TURNOUT NB I-95 MM249 |
Scenic Vista-NO FACILITIES |
| -68.534061 | 45.598464 | REST AREA SB I-95 MM240 |
RR, PT, Pets, HF |
| -68.539034 | 45.594001 | REST AREA NB I-95 MM240 |
RR, PT, Pets, HF |

10
Chapter 1

2. If we have a header row in the CSV file, then we include :header true in the call to
read-dataset:

user=> (read-dataset "data/RestAreasCombined(Ver.BJ)-headers.csv"


:header true)

| :longitude | :latitude | :name


| :codes |
|------------+-----------+--------------------------------------+-
---------------------------|
| -67.834062 | 46.141129 | REST AREA-FOLLOW SIGNS SB I-95 MM305 |
RR, PT, Pets, HF |
| -67.845906 | 46.138084 | REST AREA-FOLLOW SIGNS NB I-95 MM305 |
RR, PT, Pets, HF |
| -68.498471 | 45.659781 | TURNOUT NB I-95 MM249 |
Scenic Vista-NO FACILITIES |
| -68.534061 | 45.598464 | REST AREA SB I-95 MM240 |
RR, PT, Pets, HF |
| -68.539034 | 45.594001 | REST AREA NB I-95 MM240 |
RR, PT, Pets, HF |

How it works…
Together, Clojure and Incanter make a lot of common tasks easy, which is shown in the How to
do it section of this recipe.

We've taken some external data, in this case from a CSV file, and loaded it into an Incanter
dataset. In Incanter, a dataset is a table, similar to a sheet in a spreadsheet or a database
table. Each column has one field of data, and each row has an observation of data. Some
columns will contain string data (all of the columns in this example did), some will contain
dates, and some will contain numeric data. Incanter tries to automatically detect when a
column contains numeric data and coverts it to a Java int or double. Incanter takes away a
lot of the effort involved with importing data.

There's more…
For more information about Incanter datasets, see Chapter 6, Working with Incanter Datasets.

11
Importing Data for Analysis

Reading JSON data into Incanter datasets


Another data format that's becoming increasingly popular is JavaScript Object Notation
(JSON, http://json.org/). Like CSV, this is a plain text format, so it's easy for programs to
work with. It provides more information about the data than CSV does, but at the cost of being
more verbose. It also allows the data to be structured in more complicated ways, such as
hierarchies or sequences of hierarchies.

Because JSON is a much richer data model than CSV, we might need to transform the
data. In that case, we can just pull out the information we're interested in and flatten the
nested maps before we pass it to Incanter. In this recipe, however, we'll just work with fairly
simple data structures.

Getting ready
First, here are the contents of the Leiningen project.clj file:
(defproject getting-data "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.6.0"]
[incanter "1.5.5"]
[org.clojure/data.json "0.2.5"]])

Use these libraries in your REPL or program (inside an ns form):


(require '[incanter.core :as i]
'[clojure.data.json :as json]
'[clojure.java.io :as io])
(import '[java.io EOFException])

Moreover, you need some data. For this, I have a file named delicious-rss-214k.json
and placed it in the folder named data. It contains a number of top-level JSON objects.
For example, the first one starts like this:
{
"guidislink": false,
"link": "http://designreviver.com/tips/a-collection-of-wordpress-
tutorials-tips-and-themes/",
"title_detail": {
"base": "http://feeds.delicious.com/v2/rss/
recent?min=1&count=100",
"value": "A Collection of Wordpress Tutorials, Tips and Themes
| Design Reviver",
"language": null,
"type": "text/plain"
},
"author": "mccarrd4",

12
Chapter 1

You can download this data file from Infochimps at http://www.ericrochester.com/


clj-data-analysis/data/delicious-rss-214k.json.xz. You'll need to decompress
it into the data directory.

How to do it…
Once everything's in place, we'll need a couple of functions to make it easier to handle the
multiple JSON objects at the top level of the file:

1. We'll need a function that attempts to call a function on an instance of java.


io.Reader and returns nil if there's an EOFException, in case there's a
problem reading the file:
(defn test-eof [reader f]
(try
(f reader)
(catch EOFException e
nil)))

2. Now, we'll build on this to repeatedly parse a JSON document from an instance of
java.io.Reader. We do this by repeatedly calling test-eof until eof or until it
returns nil, accumulating the returned values as we go:
(defn read-all-json [reader]
(loop [accum []]
(if-let [record (test-eof reader json/read)]
(recur (conj accum record))
accum)))

3. Finally, we'll perform the previously mentioned two steps to read the data from
the file:
(def d (i/to-dataset
(with-open
[r (io/reader
"data/delicious-rss-214k.json")]
(read-all-json r))))

This binds d to a new dataset that contains the information read in from the JSON documents.

13
Importing Data for Analysis

How it works…
Similar to all Lisp's (List Processing), Clojure is usually read from the inside out and from
right to left. Let's break it down. clojure.java.io/reader opens the file for reading.
read-all-json parses all of the JSON documents in the file into a sequence. In this case, it
returns a vector of the maps. incanter.core/to-dataset takes a sequence of maps and
returns an Incanter dataset. This dataset will use the keys in the maps as column names, and
it will convert the data values into a matrix. Actually, to-dataset can accept many different
data structures. Try doc to-dataset in the REPL (doc shows the documentation string
attached to the function), or see the Incanter documentation at http://data-sorcery.
org/contents/ for more information.

Reading data from Excel with Incanter


We've seen how Incanter makes a lot of common data-processing tasks very simple, and
reading an Excel spreadsheet is another example of this.

Getting ready
First, make sure that your Leiningen project.clj file contains the right dependencies:
(defproject getting-data "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.6.0"]
[incanter "1.5.5"]"]])

Also, make sure that you've loaded those packages into the REPL or script:
(use 'incanter.core
'incanter.excel)

Find the Excel spreadsheet you want to work on. The file name of my spreadsheet is data/
small-sample-header.xls, as shown in the following screenshot. You can download this
from http://www.ericrochester.com/clj-data-analysis/data/small-sample-
header.xls.

14
Chapter 1

How to do it…
Now, all you need to do is call incanter.excel/read-xls:
user=> (read-xls "data/small-sample-header.xls")

| given-name | surname | relation |


|------------+---------+-------------|
| Gomez | Addams | father |
| Morticia | Addams | mother |
| Pugsley | Addams | brother |

How it works…
This can read standard Excel files (.xls) and the XML-based file format introduced in
Excel 2003 (.xlsx).

Reading data from JDBC databases


Reading data from a relational database is only slightly more complicated than reading from
Excel, and much of the extra complication involves connecting to the database.

Fortunately, there's a Clojure-contributed package that sits on top of JDBC (the Java database
connector API, http://www.oracle.com/technetwork/java/javase/jdbc/index.
html) and makes working with databases much easier. In this example, we'll load a table
from an SQLite database (http://www.sqlite.org/), which stores the database in a
single file.

Getting ready
First, list the dependencies in your Leiningen project.clj file. We will also need to include
the database driver library. For this example, it is org.xerial/sqlite-jdbc:
(defproject getting-data "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.6.0"]
[incanter "1.5.5"]
[org.clojure/java.jdbc "0.3.3"]
[org.xerial/sqlite-jdbc "3.7.15-M1"]])

Then, load the modules into your REPL or script file:


(require '[incanter.core :as i]
'[clojure.java.jdbc :as j])

15
Importing Data for Analysis

Finally, get the database connection information. I have my data in an SQLite database file
named data/small-sample.sqlite, as shown in the following screenshot. You can
download this from http://www.ericrochester.com/clj-data-analysis/data/
small-sample.sqlite.

How to do it…
Loading the data is not complicated, but we'll make it easier with a wrapper function:

1. We'll create a function that takes a database connection map and a table name and
returns a dataset created from this table:
(defn load-table-data
"This loads the data from a database table."
[db table-name]
(i/to-dataset
(j/query db (str "SELECT * FROM " table-name ";"))))

16
Chapter 1

2. Next, we define a database map with the connection parameters suitable for
our database:
(defdb {:subprotocol "sqlite"
:subname "data/small-sample.sqlite"
:classname "org.sqlite.JDBC"})

3. Finally, call load-table-data with db and a table name as a symbol or string:


user=> (load-table-data db 'people)

| :relation | :surname | :given_name |


|-------------+----------+-------------|
| father | Addams | Gomez |
| mother | Addams | Morticia |
| brother | Addams | Pugsley |||

How it works…
The load-table-data function passes the database connection information directly
through to clojure.java.jdbc/query.query. It creates an SQL query that returns all
of the fields in the table that is passed in. Each row of the result is a sequence of hashes
mapping column names to data values. This sequence is wrapped in a dataset by
incanter.core/to-dataset.

See also
Connecting to different database systems using JDBC isn't necessarily a difficult task,
but it's dependent on which database you wish to connect to. Oracle has a tutorial for
how to work with JDBC at http://docs.oracle.com/javase/tutorial/jdbc/
basics, and the documentation for the clojure.java.jdbc library has some good
information too (http://clojure.github.com/java.jdbc/). If you're trying to find
out what the connection string looks like for a database system, there are lists available
online. The list at http://www.java2s.com/Tutorial/Java/0340__Database/
AListofJDBCDriversconnectionstringdrivername.htm includes the major drivers.

17
Importing Data for Analysis

Reading XML data into Incanter datasets


One of the most popular formats for data is XML. Some people love it, while some hate it.
However, almost everyone has to deal with it at some point. While Clojure can use Java's
XML libraries, it also has its own package which provides a more natural way to work with
XML in Clojure.

Getting ready
First, include these dependencies in your Leiningen project.clj file:
(defproject getting-data "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.6.0"]
[incanter "1.5.5"]])

Use these libraries in your REPL or program:


(require '[incanter.core :as i]
'[clojure.xml :as xml]
'[clojure.zip :as zip])

Then, find a data file. I visited the website for the Open Data Catalog for Washington, D.C.
(http://data.octo.dc.gov/), and downloaded the data for the 2013 crime incidents.
I moved this file to data/crime_incidents_2013_plain.xml. This is how the contents
of the file look:
<?xml version="1.0" encoding="iso-8859-1"?>
<dcst:ReportedCrimes
xmlns:dcst="http://dc.gov/dcstat/types/1.0/">
<dcst:ReportedCrime
xmlns:dcst="http://dc.gov/dcstat/types/1.0/">
<dcst:ccn><![CDATA[04104147]]></dcst:ccn>
<dcst:reportdatetime>
2013-04-16T00:00:00-04:00
</dcst:reportdatetime>

18
Chapter 1

How to do it…
Now, let's see how to load this file into an Incanter dataset:

1. The solution for this recipe is a little more complicated, so we'll wrap it into a function:
(defn load-xml-data [xml-file first-data next-data]
(let [data-map (fn [node]
[(:tag node) (first (:content node))])]
(->>
(xml/parse xml-file)
zip/xml-zip
first-data
(iterate next-data)
(take-while #(not (nil? %))
(map zip/children)
(map #(mapcat data-map %))
(map #(apply array-map %))
i/to-dataset)))

2. We can call the function like this. Because there are so many columns, we'll just
verify the data that is loaded by looking at the column names and the row count:
user=> (def d
(load-xml-data "data/crime_incidents_2013_plain.xml"
zip/down zip/right))
user=> (i/col-names d)
[:dcst:ccn :dcst:reportdatetime :dcst:shift :dcst:offense
:dcst:method :dcst:lastmodifieddate :dcst:blocksiteaddress
:dcst:blockxcoord :dcst:blockycoord :dcst:ward :dcst:anc
:dcst:district :dcst:psa :dcst:neighborhoodcluster :dcst:busi
nessimprovementdistrict :dcst:block_group :dcst:census_tract
:dcst:voting_precinct :dcst:start_date :dcst:end_date]
user=> (i/nrow d)
35826

This looks good. This gives you the number of crimes reported in the dataset.

How it works…
This recipe follows a typical pipeline for working with XML:

1. Parsing an XML data file


2. Extracting the data nodes
3. Converting the data nodes into a sequence of maps representing the data
4. Converting the data into an Incanter dataset

19
Importing Data for Analysis

load-xml-data implements this process. This takes three parameters:

ff The input filename


ff A function that takes the root node of the parsed XML and returns the first data node
ff A function that takes a data node and returns the next data node or nil, if there are
no more nodes

First, the function parses the XML file and wraps it in a zipper (we'll talk more about zippers in
the next section). Then, it uses the two functions that are passed in to extract all of the data
nodes as a sequence. For each data node, the function retrieves that node's child nodes and
converts them into a series of tag name / content pairs. The pairs for each data node are
converted into a map, and the sequence of maps is converted into an Incanter dataset.

There's more…
We used a couple of interesting data structures or constructs in this recipe. Both are common
in functional programming or Lisp, but neither have made their way into more mainstream
programming. We should spend a minute with them.

Navigating structures with zippers


The first thing that happens to the parsed XML is that it gets passed to clojure.zip/
xml-zip. Zippers are standard data structures that encapsulate the data at a position in a
tree structure, as well as the information necessary to navigate back out. This takes Clojure's
native XML data structure and turns it into something that can be navigated quickly using
commands such as clojure.zip/down and clojure.zip/right. Being a functional
programming language, Clojure encourages you to use immutable data structures, and
zippers provide an efficient, natural way to navigate and modify a tree-like structure, such as
an XML document.

Zippers are very useful and interesting, and understanding them can help you understand
and work better with immutable data structures. For more information on zippers, the
Clojure-doc page is helpful (http://clojure-doc.org/articles/tutorials/
parsing_xml_with_zippers.html). However, if you would rather dive into the deep
end, see Gerard Huet's paper, The Zipper (http://www.st.cs.uni-saarland.de/edu/
seminare/2005/advanced-fp/docs/huet-zipper.pdf).

Processing in a pipeline
We used the ->> macro to express our process as a pipeline. For deeply nested function calls,
this macro lets you read it from the left-hand side to the right-hand side, and this makes the
process's data flow and series of transformations much more clear.

20
Chapter 1

We can do this in Clojure because of its macro system. ->> simply rewrites the calls into
Clojure's native, nested format as the form is read. The first parameter of the macro is
inserted into the next expression as the last parameter. This structure is inserted into the third
expression as the last parameter, and so on, until the end of the form. Let's trace this through
a few steps. Say, we start off with the expression (->> x first (map length) (apply
+)). As Clojure builds the final expression, here's each intermediate step (the elements to be
combined are highlighted at each stage):

1. (->> x first (map length) (apply +))


2. (->>(first x) (map length) (apply +))
3. (->>(map length (first x)) (apply +))
4. (apply + (map length (first x)))

Comparing XML and JSON


XML and JSON (from the Reading JSON data into Incanter datasets recipe) are very similar.
Arguably, much of the popularity of JSON is driven by disillusionment with XML's verboseness.

When we're dealing with these formats in Clojure, the biggest difference is that JSON is
converted directly to native Clojure data structures that mirror the data, such as maps and
vectors Meanwhile, XML is read into record types that reflect the structure of XML, not the
structure of the data.

In other words, the keys of the maps for JSON will come from the domains, first_name or
age, for instance. However, the keys of the maps for XML will come from the data format, such
as tag, attribute, or children, and the tag and attribute names will come from the domain.
This extra level of abstraction makes XML more unwieldy.

Scraping data from tables in web pages


There's data everywhere on the Internet. Unfortunately, a lot of it is difficult to reach. It's
buried in tables, articles, or deeply nested div tags. Web scraping (writing a program that
walks over a web page and extracts data from it) is brittle and laborious, but it's often the only
way to free this data so it can be used in our analyses. This recipe describes how to load a
web page and dig down into its contents so that you can pull the data out.

To do this, we're going to use the Enlive (https://github.com/cgrand/enlive/wiki)


library. This uses a domain specific language (DSL, a set of commands that make a small set
of tasks very easy and natural) based on CSS selectors to locate elements within a web page.
This library can also be used for templating. In this case, we'll just use it to get data back out
of a web page.

21
Importing Data for Analysis

Getting ready
First, you have to add Enlive to the dependencies in the project.clj file:
(defproject getting-data "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.6.0"]
[incanter "1.5.5"]
[enlive "1.1.5"]])

Next, use these packages in your REPL or script:


(require '[clojure.string :as string]
'[net.cgrand.enlive-html :as html]
'[incanter.core :as i])
(import [java.net URL])

Finally, identify the file to scrape the data from. I've put up a file at http://www.
ericrochester.com/clj-data-analysis/data/small-sample-table.html,
which looks like this:

It's intentionally stripped down, and it makes use of tables for layout (hence the comment
about 1999).

22
Chapter 1

How to do it…
1. Since this task is a little complicated, let's pull out the steps into several functions:
(defn to-keyword
"This takes a string and returns a normalized keyword."
[input]
(->input
string/lower-case
(string/replace \space \-)
keyword))

(defn load-data
"This loads the data from a table at a URL."
[url]
(let [page (html/html-resource (URL. url))
table (html/select page [:table#data])
headers (->>
(html/select table [:tr :th])
(map html/text)
(map to-keyword)
vec)
rows (->> (html/select table [:tr])
(map #(html/select % [:td]))
(map #(map html/text %))
(filterseq))]
(i/dataset headers rows))))))

2. Now, call load-data with the URL you want to load data from:
user=> (load-data (str "http://www.ericrochester.com/"
"clj-data-analysis/data/small-sample-table.html"))
| :given-name | :surname | :relation |
|-------------+----------+-------------|
| Gomez | Addams | father |
| Morticia | Addams | mother |
| Pugsley | Addams | brother |
| Wednesday | Addams | sister |

23
Importing Data for Analysis

How it works…
The let bindings in load-data tell the story here. Let's talk about them one by one.

The first binding has Enlive download the resource and parse it into Enlive's internal
representation:
(let [page (html/html-resource (URL. url))

The next binding selects the table with the data ID:
table (html/select page [:table#data])

Now, select of all the header cells from the table, extract the text from them, convert each to a
keyword, and then convert the entire sequence into a vector. This gives headers for the dataset:
headers (->>
(html/select table [:tr :th])
(map html/text)
(map to-keyword)
vec)

First, select each row individually. The next two steps are wrapped in map so that the cells in
each row stay grouped together. In these steps, select the data cells in each row and extract
the text from each. Last, use filterseq, which removes any rows with no data, such as the
header row:
rows (->> (html/select table [:tr])
(map #(html/select % [:td]))
(map #(map html/text %))
(filterseq))]

Here's another view of this data. In this image, you can see some of the code from this web
page. The variable names and select expressions are placed beside the HTML structures that
they match. Hopefully, this makes it more clear how the select expressions correspond to the
HTML elements:

24
Chapter 1

Finally, convert everything to a dataset. incanter.core/dataset is a lower level


constructor than incanter.core/to-dataset. It requires you to pass in the column
names and data matrix as separate sequences:
(i/dataset headers rows)))

It's important to realize that the code, as presented here, is the result of a lot of trial and error.
Screen scraping usually is. Generally, I download the page and save it, so I don't have to keep
requesting it from the web server. Next, I start the REPL and parse the web page there. Then,
I can take a look at the web page and HTML with the browser's view source function, and I can
examine the data from the web page interactively in the REPL. While working, I copy and paste
the code back and forth between the REPL and my text editor, as it's convenient. This workflow
and environment (sometimes called REPL-driven-development) makes screen scraping
(a fiddly, difficult task at the best of times) almost enjoyable.

See also
ff The next recipe, Scraping textual data from web pages, has a more involved example
of data scraping on an HTML page
ff The Aggregating data from different formats recipe has a practical, real-life example
of data scraping in a table

Scraping textual data from web pages


Not all of the data on the Web is in tables, as in our last recipe. In general, the process
to access this nontabular data might be more complicated, depending on how the page
is structured.

Getting ready
First, we'll use the same dependencies and the require statements as we did in the last
recipe, Scraping data from tables in web pages.

Next, we'll identify the file to scrape the data from. I've put up a file at http://www.
ericrochester.com/clj-data-analysis/data/small-sample-list.html.

This is a much more modern example of a web page. Instead of using tables, it marks up the
text with the section and article tags and other features from HTML5, which help convey
what the text means, not just how it should look.

25
Importing Data for Analysis

As the screenshot shows, this page contains a list of sections, and each section contains a list
of characters:

How to do it…
1. Since this is more complicated, we'll break the task down into a set of
smaller functions:
(defn get-family
"This takes an article element and returns the family
name."
[article]
(string/join
(map html/text (html/select article [:header :h2]))))

26
Chapter 1
(defn get-person
"This takes a list item and returns a map of the person's
name and relationship."
[li]
(let [[{pnames :content} rel] (:content li)]
{:name (apply str pnames)
:relationship (string/trim rel)}))

(defn get-rows
"This takes an article and returns the person mappings,
with the family name added."
[article]
(let [family (get-family article)]
(map #(assoc % :family family)
(map get-person
(html/select article [:ul :li])))))

(defn load-data
"This downloads the HTML page and pulls the data out of
it."
[html-url]
(let [html (html/html-resource (URL. html-url))
articles (html/select html [:article])]
(i/to-dataset (mapcat get-rows articles))))

2. Now that these functions are defined, we just call load-data with the URL that we
want to scrape:
user=> (load-data (str "http://www.ericrochester.com/"
"clj-data-analysis/data/"
"small-sample-list.html"))
| :family | :name | :relationship |
|----------------+-----------------+---------------|
| Addam's Family | Gomez Addams | — father |
| Addam's Family | Morticia Addams | — mother |
| Addam's Family | Pugsley Addams | — brother |

27
Importing Data for Analysis

How it works…
After examining the web page, each family is wrapped in an article tag that contains a
header with an h2 tag. get-family pulls that tag out and returns its text.

get-person processes each person. The people in each family are in an unordered list
(ul), and each person is in an li tag. The person's name itself is in an em tag. let gets the
contents of the li tag and decomposes it in order to pull out the name and relationship
strings. get-person puts both pieces of information into a map and returns it.

get-rows processes each article tag. It calls get-family to get that information from
the header, gets the list item for each person, calls get-person on the list item, and adds
the family to each person's mapping.

Here's how the HTML structures correspond to the functions that process them. Each function
name is mentioned beside the elements it parses:

Finally, load-data ties the process together by downloading and parsing the HTML file and
pulling the article tags from it. It then calls get-rows to create the data mappings and
converts the output to a dataset.

28
Chapter 1

Reading RDF data


More and more data is going up on the Internet using linked data in a variety of formats
such as microformats, RDFa, and RDF/XML.

Linked data represents entities as consistent URLs and includes links to other databases
of the linked data. In a sense, it's the computer equivalent of human-readable web
pages. Often, these formats are used for open data, such as the data published by some
governments, like in the UK and elsewhere.

Linked data adds a lot of flexibility and power, but it also introduces more complexity.
Often, to work effectively with linked data, we need to start a triple store of some kind.
In this recipe and the next three, we'll use Sesame (http://rdf4j.org/) and the
kr Clojure library (https://github.com/drlivingston/kr).

Getting ready
First, we need to make sure that the dependencies are listed in our Leiningen
project.clj file:

(defproject getting-data "0.1.0-SNAPSHOT"


:dependencies [[org.clojure/clojure "1.6.0"]
[incanter "1.5.5"]
[edu.ucdenver.ccp/kr-sesame-core "1.4.17"]
[org.clojure/tools.logging "0.3.0"]
[org.slf4j/slf4j-simple "1.7.7"]])

We'll execute these packages to have these loaded into our script or REPL:
(use 'incanter.core
'edu.ucdenver.ccp.kr.kb
'edu.ucdenver.ccp.kr.rdf
'edu.ucdenver.ccp.kr.sparql
'edu.ucdenver.ccp.kr.sesame.kb
'clojure.set)
(import [java.io File])

For this example, we'll get data from the Telegraphis Linked Data assets. We'll pull down the
database of currencies at http://telegraphis.net/data/currencies/currencies.
ttl. Just to be safe, I've downloaded that file and saved it as data/currencies.ttl, and
we'll access it from there.

We'll store the data, at least temporarily, in a Sesame data store (http://notes.3kbo.
com/sesame) that allows us to easily store and query linked data.

29
Importing Data for Analysis

How to do it…
The longest part of this process will be to define the data. The libraries we're using do all of
the heavy lifting, as shown in the steps given below:

1. First, we will create the triple store and register the namespaces that the data uses.
We'll bind this triple store to the name tstore:
(defn kb-memstore
"This creates a Sesame triple store in memory."
[]
(kb :sesame-mem))
(defn init-kb [kb-store]
(register-namespaces
kb-store
'(("geographis"
"http://telegraphis.net/ontology/geography/geography#")
("code"
"http://telegraphis.net/ontology/measurement/code#")
("money"
"http://telegraphis.net/ontology/money/money#")
("owl"
"http://www.w3.org/2002/07/owl#")
("rdf"
"http://www.w3.org/1999/02/22-rdf-syntax-ns#")
("xsd"
"http://www.w3.org/2001/XMLSchema#")
("currency"
"http://telegraphis.net/data/currencies/")
("dbpedia" "http://dbpedia.org/resource/")
("dbpedia-ont" "http://dbpedia.org/ontology/")
("dbpedia-prop" "http://dbpedia.org/property/")
("err" "http://ericrochester.com/"))))

(def t-store (init-kb (kb-memstore)))

30
Random documents with unrelated
content Scribd suggests to you:
So geschah es auch! Im nächsten Jahr wurde er Budgetkontrolleur
des Reichstages. Er blieb zwei Monate auf Reisen fort. Jetzt fühlte
die Baronin, dass sie ihn liebte; sie fühlte es, weil sie fürchtete, den
zu verlieren, der sie so für sich eingenommen hatte.
Als er zurückkam, war sie Feuer und Flamme; er aber hatte den
Kopf voll von dem, was er während der Reise gesehen und gehört.
Er sah wohl ein, dass der Augenblick der Trennung gekommen sei,
aber er wollte sie aufschieben, sie verhindern, wenn es möglich war.
Er zeigte ihr in grossen lebenden Bildern, wie diese kolossale
Riesenmaschine, die Staat heisst, eingerichtet ist; suchte den Gang
der Räder zu erklären, die Mannigfaltigkeit der Übertragungen, die
Regulatoren und Sperrhaken, schlechte Pendel und unsichere
Ventile.
Eine Weile folgte sie ihm, dann aber ermüdete sie. Ihre
Inferiorität, ihre Wertlosigkeit fühlend, warf sie sich auf die
Erziehung des Kindes; als Muster einer Mutter wollte sie zeigen, dass
sie doch einen Wert besass. Aber der Mann wusste diesen Wert nicht
zu schätzen. Er hatte sich mit einem guten Kameraden verheiratet,
und nun hatte er eine gute Bonne. Wer konnte das ändern? Wer
konnte alles voraussehen?
Das Haus war jetzt voller Abgeordneter, und die Herren sprachen
über Politik beim Essen. Die Frau beschränkte sich darauf,
nachzusehen, dass tadellos serviert wurde. Der Baron dachte
allerdings immer daran, neben die Wirtin junge Leute zu setzen, die
über Theater und Musik mit ihr sprachen; aber die Baronin
antwortete immer mit Kindererziehung. Beim Nachtisch vergass man
nie, auf das Wohl der Wirtin zu trinken, floh dann aber Hals über
Kopf ins Zimmer des Mannes, um dort zu rauchen und die Politik
fortzusetzen. Die Baronin ging dann in die Kinderstube und fühlte
mit Bitterkeit, dass er ihr jetzt so weit voraus war, dass sie ihn nie
mehr einholen konnte.
Er arbeitete abends viel zu Hause und schrieb bis tief in die Nacht,
schloss sich aber immer ein. Wenn er dann seine Frau verweint sah,
fühlte er einen Stich im Herzen, aber sie hatten ja einander nichts zu
sagen.
Zuweilen aber, wenn die Arbeit ihn ekelte, wenn er fühlte, wie
seine eigene Persönlichkeit immer ärmer wurde, empfand er eine
Leere, eine Sehnsucht nach etwas Warmem, Intimem, von dem er
ein Mal in seiner Jugend geträumt hatte. Aber jedes Gefühl der Art
verbot er sich als Untreue, und er hatte eine tiefe Vorstellung von
der Pflicht gegen seine Frau.
Um ihr das Leben etwas erträglicher zu machen, schlug er ihr vor,
sie möge eine Kusine, von der sie immer gesprochen und die er nie
gesehen, einladen, bei ihnen den Winter zu verbringen.
Das war lange der Wunsch der Baronin gewesen, als er jetzt aber
erfüllt werden sollte, wollte sie nicht. Sie wollte es bestimmt nicht.
Der Mann verlangte Gründe; sie konnte aber keine angeben. Das
reizte seine Neugier, und schliesslich gestand sie, ihr sei bange vor
der Kusine: die werde ihr ihren Mann nehmen, er werde sich in sie
verlieben.
– Das muss ja ein sonderbares Mädchen sein, das müssen wir
sehen.
Die Baronin weinte und warnte, aber der Baron lachte, und die
Kusine kam.
Es war eines Mittags. Der Baron kam wie gewöhnlich müde nach
Haus, hatte die Kusine wie seine Neugier nach ihr vergessen. Sie
setzten sich zu Tisch. Der Baron fragte die Kusine, ob sie Theater
liebe. Nein, das tue sie nicht. Sie liebe mehr die Wirklichkeit als
deren Scheinbild. Sie habe zu Hause eine Schule für Lumpen
eingerichtet und einen Verein für freigelassene Gefangene
gegründet. Aha! Der Baron studierte gerade das Gefängniswesen.
Die Kusine konnte ihm manche Auskunft geben. Und bis das Essen
zu Ende war, wurde über Gefängniswesen gesprochen. Schliesslich
hatte die Kusine versprochen, die Frage in einer kleinen Schrift zu
behandeln, die der Baron durchsehen und ausarbeiten wollte.
Alles was die Baronin vorausgesehen, traf ein. Der Herr Baron
schloss eine geistige Ehe mit der Kusine, und die Frau war verlassen.
Aber die Kusine war auch schön, und wenn sie sich am Schreibtisch
über den Baron beugte, empfand er ein warmes Behagen daran,
ihren weichen Arm an seiner Schulter zu fühlen und ihren heissen
Atem auf seiner Wange zu spüren. Und sie sprachen nicht immer
vom Gefängniswesen. Sie sprachen auch von Liebe. Sie glaubte an
die Liebe der Seelen und sie erklärte so deutlich, wie sie konnte,
eine Ehe ohne die Liebe der Seelen sei Prostitution. Der Baron hatte
die Entwicklung der neuen Ansichten über die Liebe nicht
mitgemacht und fand, es sei eine harte Rede, aber doch wohl nicht
ganz unbegründet.
Aber die Kusine hatte auch andere Eigenschaften, die unschätzbar
waren für eine richtige geistige Ehe. Sie vertrug Tabak und konnte
Zigaretten rauchen. Daher konnte sie nach dem Diner mit den
Herren ins Rauchzimmer gehen, um über Politik mitzusprechen.
Dann war sie entzückend.
Von kleinen Gewissensbissen geplagt, konnte der Baron dann
aufstehen, für einen Augenblick zu seiner Frau in die Kinderstube
gehen, sie und das Kind küssen und fragen, wie es ihnen gehe. Und
die Baronin war dankbar, aber sie war nicht glücklich. Der Baron
kehrte dann in brillanter Laune zur Gesellschaft zurück, als habe er
eine Pflicht erfüllt. Oft allerdings verstimmte es ihn, dass seine Frau,
als seine Frau, nicht dabei sein konnte; und er fühlte sich von dieser
Last bedrückt.
Als der Frühling kam, fuhr die Kusine nicht nach Haus, sondern
begleitete das Ehepaar in einen Badeort. Dort führte sie für die
Armen kleine Schauspiele auf, und sie und der Baron spielten gegen
einander, natürlich Liebhaber und Liebhaberin. Das hatte die ganz
natürliche Folge, dass die Flamme aufloderte. Aber es war nur
geistiges Feuer. Gemeinsame Interessen, dieselben Ansichten, und
vielleicht ähnliche Naturen.
Die Baronin hatte Zeit genug gehabt, um über ihre Stellung
nachzudenken. Eines Tages sagte sie dem Mann, da es zwischen
ihnen aus sei, so sei es das Beste, sich zu trennen. Das wollte er
denn doch nicht, und Verzweiflung ergriff ihn. Die Kusine sollte nach
Haus reisen und seine Frau sollte sehen, dass er ein Mann von Ehre
sei.
Die Kusine reiste ab. Aber der Briefwechsel begann. Die Baronin
musste alle Briefe lesen. Sie wollte es nicht, aber der Baron
verlangte es. Bald aber gab er nach und las seine Briefe allein.
Schliesslich kam die Kusine zurück! Da brach es los! Der Baron
hatte entdeckt, dass er nicht mehr ohne sie leben könne! Was war
zu tun? Trennung? Das wäre der Tod! Fortsetzen? Unmöglich! Die
Ehe auflösen, die der Baron jetzt nur noch für eine Prostitution hielt,
und sich mit einander verheiraten? Ja, das war das einzig Ehrliche,
wenn es auch schmerzhaft war.
Das aber wollte die Kusine nicht! Es sollte nicht heissen, sie habe
einen Mann von seiner Frau gelockt; und der Skandal, der Skandal!
– Aber es sei unehrlich, wenn er seiner Frau nicht alles sage; es
sei unehrlich, weiter zu gehen; man wisse nicht, wie weit es gehen
könne.
– Was? Was meine er? Wie weit könne es gehen?
– Das könne man nicht wissen!
– Oh, wie schändlich! Was er von ihr denke?
– Dass sie ein Weib sei!
Und er fiel auf die Knie und betete sie an und erklärte, der Teufel
möge ihr Gefängniswesen und ihre Schulen für Lumpen holen, er
wisse nicht, ob sie die oder die sei, aber er wisse, dass er sie liebe.
Da verachtete sie ihn und reiste Hals über Kopf nach Paris.
Er reiste ihr augenblicklich nach. Von Hamburg schrieb er einen
Brief an seine Frau. Erklärte, sie hätten einen Irrtum begangen, und
es sei unmoralisch, den nicht zu berichtigen. Bat um Scheidung.
Sie liessen sich scheiden.

Ein Jahr später war der Baron mit der Kusine verheiratet. Sie
bekamen ein Kind. Aber das störte ihr Glück nicht, im Gegenteil.
Wieviel neue Ideen hier draussen keimten, wieviel starke Winde hier
draussen wehten!
Er veranlasste sie, ein Buch über „Junge Verbrecher“ zu schreiben.
Das wurde von der Kritik heruntergemacht. Da ward sie wütend, und
schwur, nie wieder zu schreiben. Er nahm sich die Freiheit, sie zu
fragen, ob sie schreibe, um gelobt zu werden; ob sie ehrgeizig sei. –
Sie antwortete mit der Frage, weshalb er denn schreibe! – So
entstand ein kleiner Wortwechsel. – Es sei ja nur erfrischend, einmal
eine andere Ansicht zu hören als immer die eigene. – Immer die
eigene? Was solle das heissen? Habe sie nicht ihre Ansichten? – Sie
setzte jetzt ihren Stolz darin, zu zeigen, dass sie eigene Ansichten
besitze, und die mussten darum immer von denen des Mannes
verschieden sein, damit kein Irrtum vorkam. – Da erklärte er, sie
könne Ansichten haben, welche sie wolle, wenn sie ihn nur liebe. –
Liebe? Was sei denn das! Er sei ja ein Tier wie alle andern Männer,
und er sei falsch gegen sie gewesen. Nicht ihre Seele liebe er,
sondern ihren Körper. – Nein, beide, sie ganz und gar! – O, wie
falsch er gewesen! – Nein, nicht falsch, sondern der Raub eines
Selbstbetrugs sei er gewesen, als er glaubte, nur ihre Seele zu
lieben.
Sie hatten sich müde gegangen auf dem Boulevard und mussten
sich vor einem Café niedersetzen. Sie steckte sich eine Zigarette an.
Da trat der Kellner heran und sagte recht unhöflich, man dürfe hier
nicht rauchen. Der Baron verlangte eine Erklärung. Der Kellner
antwortete, es sei ein besseres Café, das seine Gäste nicht
verscheuchen wolle, indem es „solche Damen“ hereinlasse.
Sie standen auf, bezahlten und gingen. Der Baron war zornig, der
jungen Baronin kamen die Tränen. – Da habe man die Macht des
Vorurteils! Rauchen sei für den Mann eine Dummheit, denn es sei
dumm zu rauchen, aber für die Frau sei es ein Verbrechen! Wer es
könnte, möge dieses Vorurteil aufheben! Und wer es wolle! Der
Baron wollte nicht, dass seine Frau das erste Opfer werde, mit der
dürftigen Ehre, mit dem Vorurteil gebrochen zu haben. Denn etwas
anderes sei es ja nicht. In Russland rauchten ja die Damen der
Gesellschaft zwischen den Gerichten der grossen Diners. Die Sitten
änderten sich mit den Breitengraden. Und doch seien diese
Kleinigkeiten nicht bedeutungslos im Leben, denn das Leben bestehe
aus Kleinigkeiten. Hätten Männer und Frauen dieselben schlechten
Gewohnheiten, könnten sie leichter mit einander verkehren,
einander kennen lernen und eher gleichen Schritt mit einander
halten als jetzt! Hätten sie dieselbe Erziehung, so würden sie
dieselben Interessen haben und während des ganzen Lebens nicht
aus einander kommen.
Der Baron hielt inne, als habe er etwas Dummes gesagt. Aber sie
hörte nicht zu, denn ihre Gedanken waren nicht bei der
Beschimpfung stehen geblieben.
– Sie sei von einem Kellner beschimpft, aus der besseren
Gesellschaft gewiesen worden. Dahinter liege etwas! Bestimmt! Man
habe sie erkannt! Sicher, denn sie habe es schon früher bemerkt!
– Was habe sie bemerkt?
– Dass man sie in Restaurants mit Geringschätzung behandle. Die
Menschen hielten sie nicht für Eheleute, weil sie Arm in Arm gingen
und höflich gegen einander seien. Lange habe sie das mit sich
herumgetragen, nun aber vermöchte sie es nicht mehr. Aber das sei
nichts gegen das, was sie von Hause hören müsse!
– Was habe sie denn von Hause gehört, das sie ihm nicht
mitgeteilt?
– Oh, was für Dinge! Was für Briefe! Und die anonymen erst!
– Nun, und er? Man behandle ihn wie einen Verbrecher! Und er
habe doch kein Verbrechen begangen! Er habe alle gesetzlichen
Forderungen beobachtet und nicht die Ehe gebrochen. Er habe das
Land verlassen, wie das Gesetz vorschreibt; das königliche
Konsistorium habe sein Scheidungsgesuch bewilligt; die Geistlichkeit,
die heilige Kirche habe ihn auf gestempeltem Papier von seinem
ersten Eheversprechen entbunden; er habe es also nicht gebrochen!
Man könne ja ein ganzes Volk von dem Treueid lösen, den es seinem
Monarchen gegeben, wenn ein Land erobert wird: warum anerkenne
die Gesellschaft denn nicht die Entbindung von einem Versprechen?
Habe die Gesellschaft nicht selber dem Konsistorium das Recht
gegeben, die Ehe aufzulösen? Wie könne sich denn die Gesellschaft
als Richter über ihr eigenes Gesetz stellen? Die Gesellschaft liege
also im Streit mit sich selber! Er werde wie ein Verbrecher
behandelt! Habe nicht der Sekretär der Gesandtschaft, sein alter
Freund, als er ihm seine Karte und die seiner Frau gesandt, ihm
bloss eine Karte zurückgeschickt! Werde er nicht bei allen
öffentlichen Austeilungen von Karten übergangen!
– Oh, sie habe noch Schlimmeres ertragen müssen. Eine von ihren
Freundinnen in Paris habe ihr die Tür geschlossen, und mehrere
hätten sich auf der Strasse abgewandt, als sie ihnen begegnet sei.
Nur der weiss, wo der Schuh drückt, der ihn anhat! Sie hatten
jetzt die Schuhe an, richtige spanische Stiefel, und sie fühlten sich in
Fehde mit der Gesellschaft. Die Vornehmen hatten sie desavouiert!
Die Vornehmen! Diese Gemeinde von Halbkretins, die insgeheim wie
Hunde leben, einander aber ehren, solange es nicht zum Skandal
kommt; das heisst so lange man so ehrlich ist, den Vertrag zu
kündigen, die Verfallzeit abzuwarten und die vom Gesetz gewährte
Freiheit wiederzugewinnen. Und diese vornehme Gesellschaft sass
da in ihrer Lasterhaftigkeit und teilte soziales Ansehen aus, nach
einer Skala, auf der die Ehrlichkeit tief unter Null steht. Die
Gesellschaft war also ein Gewebe von Lüge! Dass man das nicht
längst gesehen! Jetzt aber musste man das schöne Gebäude
untersuchen, um nachzusehen, wie es mit dessen Fundament
bestellt sei.
Sie waren lange nicht so einig gewesen, wie jetzt, als sie nach
Haus kamen. Die Baronin blieb nun zu Hause bei ihrem Kind, und sie
erwartete bald ihr zweites. Dieser Kampf war für sie zu schwer, und
sie war schon müde geworden! Sie hatte alles satt! In einem elegant
möblierten und warmen Zimmer über freigelassene Gefangene
schreiben und ihnen aus gehöriger Entfernung eine gut
behandschuhte Hand reichen, das billigte die Gesellschaft; aber
einer Frau, die sich mit einem freigelassenen Ehemann verheiratet,
die Hand reichen, das wollte die Gesellschaft nicht. Warum nicht?
Die Antwort lag nicht nahe.
Der Baron stand mitten im Leben. Besuchte die Kammern, war auf
Versammlungen und überall hörte er wilde Ausbrüche gegen die
Gesellschaft. Er las Zeitungen und Zeitschriften, verfolgte die
Literatur, machte Studien. Seiner Frau drohte dasselbe Schicksal wie
der ersten: zurückzubleiben! Seltsam aber war es! Sie konnte nicht
allen Einzelheiten seiner Untersuchungen folgen, sie missbilligte
vieles in den neuen Lehren, aber sie fühlte, dass er recht habe und
für eine gute Sache wirke. Er wusste immer, dass er zu Hause eine
Zustimmung fand, die nicht müde wurde; eine Freundin, die ihm
wohl wollte. Ihr gemeinsames Schicksal trieb sie zusammen wie
erschrockene Tauben, wenn das Gewitter heraufzieht. Das Weibliche
bei ihr, das jetzt so wenig geachtet wird, und das doch nur eine
Erinnerung an die Mutter ist, an die Naturkraft, die das Weib
mitbekommen hat, brach nun hervor. Es fiel wie die Wärme eines
abendlichen Feuers über die Kinder, wie Sonnenschein über den
Mann, wie Friede über die Häuslichkeit. Er wunderte sich oft, dass er
diesen Kameraden nicht vermisste, mit dem er früher über alles
hatte sprechen können; er entdeckte, dass seine Gedanken an
Stärke gewannen, seit er sie nicht mehr sofort ausplauderte; und er
glaubte mehr an dem stillen Beifall, dem freundlichen Nicken, der
teilnehmenden Hilfe gewonnen zu haben. Er fühlte sich stärker als
früher, seine Ansichten wurden weniger kontrolliert; er war jetzt
einsam, aber nicht so einsam wie früher, denn damals stiess er oft
auf Widersprüche, die nur Zweifel erregten.

Es war Weihnachtsabend in Paris. In ihrem kleinen Châlet am Cours


la Reine war die Aufräumung beendet und ein grosser Tannenbaum
war aus dem Wald von Saint-Germain geholt. Der Baron und die
Baronin wollten nach dem Frühstück zusammen ausgehen, um
Weihnachtsgeschenke für die Kinder einzukaufen. Der Baron war
etwas gedankenvoll, denn er hatte eben eine kleine Schrift „Ist die
Oberklasse die Gesellschaft“ erscheinen lassen. Sie sassen am
Kaffeetisch in dem schönen Speisesaal, und die Türen bis zur
Kinderstube standen offen. Sie hörten, wie die Amme mit den
Kleinen spielte, und die Baronin lächelte vor Glück und Zufriedenheit.
Sie war so mild geworden, und ihre Freude war ruhig. Da schrie eins
von den Kindern, und sie stand vom Tisch auf, um nachzusehen,
warum es schreie. Im selben Augenblick kam der Diener in den
Speisesaal und brachte die Post. Der Baron öffnete zwei
Drucksachen. Die erste war eine „grosse, angesehene“ Zeitung. Er
schlug sie auf und sah sofort eine Überschrift in fetten Buchstaben:
„Ein Frevler!“ Und dann las er einige Zeilen: „Die Weihnacht ist
gekommen! Dieses Fest, das allen reinen Herzen lieb ist. Dieses Fest,
das von allen christlichen Völkern heilig gehalten wird, an dem
Friede und Versöhnung über die ganze Menschheit herrschen, an
dem sogar der Mörder sein Messer in die Tasche steckt und der Dieb
das heilige Besitzrecht achtet; dieses Fest, das besonders in den
nordischen Ländern sowohl die historischen Voraussetzungen besitzt
wie von uraltem Herkommen ist usw. Und da kommt, wie der
Gestank aus einer Kloake, ein Individuum, das sich nicht gescheut
hat, die heiligsten Bande zu brechen, und speit seine Bosheit gegen
die geachteten Mitglieder der Gesellschaft aus; eine Bosheit, die von
der kleinlichsten Rache diktiert wird ...“ Er legte die Zeitung
zusammen und steckte sie in die Tasche seines Schlafrocks. Dann
riss er die zweite Drucksache auf. Das war eine Karikatur über ihn
und seine Frau. Er liess die Zeitung den gleichen Weg gehen wie die
erste, musste sich aber beeilen, denn seine Frau trat ein. Er
beendete das Frühstück und eilte in sein Zimmer, um sich zum
Ausgehen anzukleiden. Dann gingen sie.
Die Sonne schien auf die bereiften Platanen der Champs Elysées,
und der Concordiaplatz öffnete sich wie eine grosse Oase von
Sonnenlicht mitten in der Steinwüste. Er hatte ihren Arm unter
seinem, es war ihm aber, als stütze sie ihn. Sie sprach davon, was
sie den Kindern kaufen sollten, und er antwortete, so gut er konnte.
Schliesslich unterbrach er auf ein Mal das Gespräch und fragte, ohne
eine Veranlassung dazu zu haben:
– Weisst du, was für ein Unterschied zwischen Strafe und Rache
ist?
– Nein, darüber habe ich nicht nachgedacht.
– Ich möchte wissen, ob es nicht dieser ist: wenn sich ein
anonymer Zeitungsschreiber rächt, dann ist es Strafe; wenn aber ein
namhafter Nichtzeitungsschreiber straft, dann ist es Rache! Tragen
wir uns ein unter die neuen Propheten!
Sie bat ihn, doch das Weihnachtsfest nicht zu stören, indem er von
Zeitungen spreche.
– Dieses Fest, wiederholte er für sich, an dem Friede und
Versöhnung ...
Sie gingen durch die Arkaden der Rivolistrasse, bogen in die
Boulevards ab und kauften ein. Im Grand-Hôtel essen sie. Sie war in
sonniger Laune und suchte ihn zu erheitern. Er aber blieb
gedankenvoll. Schliesslich warf er die Frage auf:
– Wie kann man ein böses Gewissen haben, wenn man recht
gehandelt hat?
Das wusste sie nicht.
– Kommt es daher, dass die Oberklasse uns dazu erzogen hat, ein
böses Gewissen zu haben, jedes Mal wenn wir uns gegen sie
erheben? Wahrscheinlich! Warum hat der nicht das Recht, die
Ungerechtigkeit anzugreifen, der von der Ungerechtigkeit gekränkt
worden ist? Weil nur der, der gekränkt worden ist, angreifen wird,
und die Oberklasse nicht angegriffen werden will. Warum habe ich
die Oberklasse früher, als ich zu ihr gehörte, nicht angegriffen? Weil
ich damals natürlich nicht wusste, was sie ist! Man muss sich von
einem Bild entfernen, um den richtigen Gesichtspunkt zu finden!
– Am Weihnachtsabend spricht man nicht von solchen Dingen.
– Es ist wahr, es ist Weihnachten, „dieses Fest ...“
Und sie fuhren nach Haus. Der Tannenbaum wurde angesteckt,
und Friede und Glück strahlten von ihm aus; aber die dunklen
Tannenzweige rochen nach Begräbnis und sahen düster aus, düster
wie das Gesicht des Barons. Dann aber kam die Amme mit den
Kleinen. Da klärte er sich auf, denn, dachte er, wenn sie
herangewachsen sind, dann werden sie in Freude ernten, was wir in
Tränen gesäet haben; dann werden sie nur ein böses Gewissen
haben, wenn sie sich gegen die Gesetze der Natur vergehen; werden
nicht wie wir jetzt von Grillen geritten werden, die mit dem
Rohrstock eingebläut, mit Pfaffengeschichten eingetrichtert, von der
Oberklasse zum Nutzen der Oberklasse verfasst sind.
Die Baronin setzte sich an den Flügel, als die Mädchen von der
Küche und der Diener hereinkamen. Und sie spielte alte wehmütige
Tänze, über die sich der Nordländer freut, und die Leute tanzten mit
den Kindern, sahen aber nicht fröhlich aus. Es war wie der schuldige
Teil eines öffentlichen Gottesdienstes.
Dann erhielten die Kinder und die Leute ihre
Weihnachtsgeschenke. Und dann mussten die Kinder schlafen
gehen.
Die Baronin ging in den Salon und setzte sich in einen Sessel. Der
Baron setzte sich auf einen Schemel ihr zu Füssen. Darauf liess er
seinen Kopf auf ihre Knie sinken. O, der war so schwer, so schwer!
Und sie streichelte ihm die Stirn, sagte aber nichts.
– Was! Er weine?
– Ja, das tue er!
Sie hatte noch nie einen Mann weinen sehen. Das war furchtbar!
Die ganze kräftige Gestalt schlotterte, aber er schluchzte nicht, und
kein Laut war von ihm zu hören.
– Warum er weine?
– Er sei so unglücklich!
– Unglücklich mit ihr?
– Nein, nein, nicht mit ihr, aber doch unglücklich!
– Sei man garstig gegen ihn gewesen?
– O, ja!
– Könne er davon sprechen?
– Nein! Er wolle nur bei ihr sitzen! Wie er ein Mal, vor langer Zeit,
bei seiner Mutter gesessen!
Sie plauderte mit ihm, wie mit einem Kind! Sie küsste seine
Augenlider und trocknete ihm das Gesicht mit ihrem Taschentuch.
Sie fühlte sich so stolz, so seltsam stark, und sie weinte nicht. Als er
sie so sah, fasste er wieder Mut.
– Dass er so schwach sein könne! Es sei doch furchtbar, dass es in
der Tat so schwer sei, diese fabrizierten Ansichten der Gegner zu
ertragen. Glaubten denn seine Feinde selber, was sie sagten?
– Schrecklicher Gedanke, aber das täten sie wohl. Man sehe ja
Steine in Kiefern festwachsen, warum nicht Ansichten in Gehirnen.
Aber sie glaube doch, dass er recht habe, dass er das Gute wolle?
– Ja, das glaube sie! Aber er dürfe nicht böse werden: vermisse er
nicht sein Kind, das erste?
– Doch gewiss, aber dem sei ja nicht zu helfen. Wenigstens jetzt
noch nicht! Aber er und die andern, die für die Zukunft arbeiteten,
müssten auch dafür eine Hilfe finden! Noch wisse er nicht wie, aber
stärkere Köpfe als seiner, und viele zusammen, würden wohl einmal
diese Frage, die jetzt unlösbar erscheine, lösen.
– Ja, das müssten sie!
– Aber ihre Ehe? Sei das noch eine rechte Ehe, da er ihr seinen
Kummer nicht sagen wolle? Sei das nicht auch Pro ...?
– Nein, das sei eine rechte Ehe, denn sie liebten einander; das
hätten er und seine erste Frau nicht getan! Sie liebten doch
einander? Könne sie das leugnen?
– Nein, lieber Geliebter, das könne sie nicht!
– Nun, dann sei es eine rechte Ehe, von Gott, von der Natur!
Unnatürliche Auslese
oder
Die Entstehung der Rasse

Der Baron hatte mit grossem und edlem Verdruss im


„Lebenssklaven“ gelesen, dass die Kinder der Oberklasse untergehen
würden, wenn sie nicht die Muttermilch von den Kindern der
Unterklasse nähmen. Er hatte Darwin gelesen und zu verstehen
geglaubt, durch die Auslese seien adelige Kinder eine höhere
Entwicklungsstufe der Gattung Mensch. Durch die Lehre von der
Erblichkeit aber hatte er einen Widerwillen gegen den Gebrauch von
Ammen gefasst: indem Blut der Unterklasse in adelige Adern fliesst,
könnten ja gewisse Begriffe, Vorstellungen, Intentionen eingepflanzt
werden. Er hatte also den Grundsatz angenommen, seine Frau solle
selber säugen; wenn ihre Milch nicht reiche, solle das Kind mit der
Flasche genährt werden. Die Milch von den Kühen zu nehmen, war
wohl sein Recht, wenn die Kühe sein eigenes Heu frassen, ohne das
sie verhungern würden oder gar nicht geboren wären.
Das Kind kam zur Welt. Es war ein Sohn! Der Vater war etwas
unruhig gewesen, bis die Schwangerschaft festgestellt wurde, denn
er selber war ein armer Teufel, aber seine Frau war sehr reich, und
er konnte nur in Genuss ihres Reichtums kommen, wenn die Ehe mit
einem gesetzlichen Erben gesegnet wurde, nach dem Erbgesetz Kap.
00, § 00. Die Freude war daher gross und ungeheuchelt. Der Sohn
war ein kleines durchsichtiges Vollblutwesen mit blauen Adern auf
der Hautfläche. Aber das Blut war trotzdem dünn. Die Mutter hatte
die Figur eines Engels, war mit ausgewählter Nahrung aufgezogen,
durch Pelzwerk gegen die ungünstigen Einflüsse des Klimas
geschützt worden, und von dieser vornehmen Blässe, die das Weib
von Rasse andeutet.
Sie gab ihrem Kinde selber die Brust. Man brauchte also nicht
Bäuerinnen zu melken, um die Ehre des Lebens zu geniessen. Das
waren alles Fabeln. Das Kind sog und schrie vierzehn Tage. Da alle
Kinder schreien, hatte das nichts zu bedeuten. Aber das Kind
magerte ab. Es magerte ganz schrecklich ab. Der Arzt wurde
gerufen. In geheimer Konsultation mit dem Mann erklärte er offen,
das Kind werde sterben, wenn die Mutter es weiter säuge, denn teils
sei sie zu nervös, teils habe sie nichts zu geben. Ja, er machte eine
quantitative Analyse der Milch und zeigte mit Gleichungen, das Kind
werde verhungern, wenn man auf diese Weise fortfahre.
Was sei zu tun, denn sterben dürfe das Kind nicht? Amme oder
Flasche. Die Amme kam nicht in Frage, unter keiner Bedingung. Wir
wollen es mit der Flasche versuchen! Der Arzt verordnete jedoch
eine Amme.
Die beste holländische Kuh, welche die goldene Medaille des
Kreises erhalten hatte, wurde isoliert und mit Heu gefüttert; mit
trocknem Heu von der Hochwiese. Der Arzt analysierte die Milch,
und alles war gut. Es war so einfach mit der Flasche! Dass man nicht
schon längst daran gedacht hatte! Und man brauchte keine Amme,
diese Haustyrannin, der man schmeicheln, dieses Faultier, das man
mästen musste; und obendrein konnte sie noch eine ansteckende
Krankheit haben!
Aber das Kind magerte trotzdem ab und schrie immer noch. Schrie
Nacht und Tag! Es hatte ganz deutlich Magenschmerzen. Eine neue
Kuh und eine neue Analyse. Die Milch wurde mit Karlsbader Wasser
(echtem Sprudel) verdünnt, aber das Kind schrie doch noch.
– Hier ist weiter nichts zu machen, als eine Amme zu nehmen,
erklärte der Arzt.
– Nein, das wolle man nicht. Man wolle andern Kindern nicht die
Milch fortnehmen, das sei unnatürlich, und man sei nicht sicher vor
der „Erblichkeit“.
Als der Baron von Natur und Unnatur sprechen wollte, konnte der
Arzt den Baron darüber aufklären, wenn man die Natur wirken lasse,
so würden alle adeligen Familien aussterben und ihr Grundbesitz an
die Krone fallen. So weise habe die Natur es eingerichtet, und die
Kultur des Menschen sei nur ein törichter Kampf gegen die Natur, in
dem der Mensch schliesslich untergehen müsse. Die Rasse des Herrn
Baron sei zum Untergang verurteilt; das zeige sich darin, dass seine
Frau nicht genügend Nahrung für die Frucht ihres Leibes habe; um
leben zu können, müsse man also die Milch von andern Weibchen
rauben oder kaufen. Die Rasse lebe also bis in die geringste
Einzelheit von Raub.
– Sei das auch Raub, wenn man die Milch kaufe? Sie kaufe!
– Ja, denn das Geld, mit dem man die Muttermilch des Volkes
kaufe, sei ja das Produkt einer Arbeit. Und wessen Arbeit? Des
Volkes! Denn der Adel arbeite ja nicht.
– Aber der Doktor sei ja Sozialist!
– Nein, er sei Darwinist. Übrigens könne man ihn seinetwegen
ruhig Sozialist nennen, das sei ihm ganz einerlei!
– Ja, aber raube man, wenn man kaufe? Das sei doch zu streng!
– Ja, wenn man mit Geld kaufe, das man nicht erarbeitet.
– Mit dem Körper also erarbeitet?
– Ja!
– Dann sei ja der Doktor auch ein Räuber!
– Gewiss! Das könne ihn aber nicht davon abhalten, die Wahrheit
zu sagen! Ob der Baron sich nicht an den reuigen Räuber erinnere,
der so wahr gesprochen?
Das Gespräch wurde abgekürzt, und der Baron liess den Professor
kommen.
Der nannte den Baron einen Mörder, weil er nicht längst für eine
Amme gesorgt habe!
Der Baron musste seine Frau überreden. Er musste seine ganze
frühere Beweisführung aufheben und die einfache Tatsache betonen:
die Liebe zu seinem Kind (verglichen mit dem Erbgesetz).
Aber wo sollte man eine Amme hernehmen? An die Stadt brauchte
man erst garnicht zu denken, denn da waren alle Menschen
verdorben! Nein, ein Mädchen vom Lande musste es sein. Aber die
Baronin wollte kein Mädchen haben, denn ein Mädchen, das ein Kind
habe, sei ja ein unsittliches Geschöpf: da könne ja der Sohn eine
erbliche Anlage bekommen.
Der Arzt sagte, alle Ammen seien Mädchen, und wenn der junge
Baron die Anlage, zu Mädchen zu gehen, erben werde, so sei er ein
tüchtigen Kerl, und solche Anlagen müsse man pflegen. Eine
Bauernfrau bekomme man bestimmt nicht, denn wer Grund und
Boden habe, wolle auch seine Kinder selber besitzen.
– Aber wenn man ein Mädchen mit einem Knecht verheirate.
– Dann müsse man neun Monate warten.
– Aber wenn man ein Mädchen verheirate, das schon ein Kind
habe?
– Das sei eine Idee!
Der Baron wusste wohl von einem Mädchen, das ein Kind von drei
Monaten hatte. Er wusste es nur allzu gut, denn seine
Verlobungszeit hatte drei Jahre gedauert und der Arzt hatte ihm
schliesslich „verordnen“ müssen, untreu zu sein.
Er ging selber zu ihr und fragte sie. Sie solle einen eigenen Hof
bekommen, wenn sie sich mit dem Knecht Anders verheirate und
Amme im Herrnhaus werde. Nun, es war klar, dass sie das lieber
wollte, als allein die Schande tragen.
Am nächsten Sonntag sollten sie zum ersten, zweiten und dritten
Mal aufgeboten werden, und Anders sollte auf zwei Monate nach
Haus reisen.
Der Baron sah ihr Kind mit einem seltsamen Gefühl von Neid. Es
war ein grosses, starkes Ding. Schön war es nicht, aber sicher würde
es sich durch viele Familienglieder fortpflanzen können. Das Kind
war zum Leben geboren, aber es wurde nicht sein Los.
Anna weinte, als es ins Waisenhaus gebracht wurde, aber das
gute Essen im Herrnhaus, denn sie ass vom Essen der Herrschaft
und bekam Porter und Wein, so viel sie wollte, tröstete sie
allmählich. Auch durfte sie ausfahren in der grossen Kalesche, auf
deren Kutschbock ein Bedienter sass. Und dann konnte sie
„Tausendundeine Nacht“ lesen. Noch nie in ihrem Leben war sie so
gepflegt worden.
Aber nach zwei Monaten kam Anders zurück. Er war bei seinen
Eltern auf Besuch gewesen. Hatte gegessen, getrunken und sich
ausgeruht. Er nahm den Hof in Besitz, verlangte aber nach seiner
Anna. Könnte sie nicht wenigstens bei ihm vorsprechen? Nein, das
wollte die Baronin nicht. Keinerlei Geschichten!
Anna begann abzunehmen und der kleine Baron schrie. Der Arzt
wurde um Rat gefragt.
– Man lasse sie zusammen, sagte er.
– Wenn das aber schädlich ist?
– Im Gegenteil!
Aber Anders sollte erst „analysiert“ werden.
Das wollte Anders nicht. Anders erhielt einige Schafe und dann
wurde er analysiert.
Der kleine Baron schrie nicht mehr.
Da aber kam die Nachricht vom Waisenhaus, Annas Junge sei an
Diphtheritis gestorben. Anna bekam Milchversetzung und der kleine
Baron schrie ganz schrecklich.
Anna musste verabschiedet und zu Anders geschickt werden, und
man musste eine neue Amme annehmen. Anders freute sich, endlich
richtig verheiratet zu sein, aber Anna hatte feine Gewohnheiten
angenommen. Sie konnte nicht mehr brasilianischen Kaffee trinken,
sondern musste Java haben. Und ihre Gesundheit verbot ihr, sechs
Mal in der Woche Fisch zu essen. Sie konnte die Erde nicht graben,
und darum wurde das Brot knapp.
Nach einem Jahr hätte Anders den Hof aufgeben müssen; doch
der Baron war ihm gewogen, und er durfte als Kätner bleiben.
Anna tagewerkte auf dem Herrnhof und sah oft den kleinen
Baron; er aber erkannte sie nicht wieder, und das war gut. Aber er
hatte doch an ihrer Brust gelegen. Und sie hatte sein Leben gerettet
und dafür das ihres eigenen Kindes gegeben. Doch sie war fruchtbar
und bekam mehrere Söhne, die Kätner, Bahnarbeiter wurden; einer
wurde Zuchthäusler.
Aber der alte Baron sah mit Unruhe den Tag kommen, an dem der
junge Baron sich verheiraten und einen Erben zeugen würde. Stark
sah er nicht aus! Er wäre sehr viel ruhiger gewesen, wenn der
andere kleine Baron, der im Waisenhaus starb, auf dem Herrnhof
gesessen hätte. Und als er den „Lebenssklaven“ noch ein Mal las,
musste er eingestehen, dass die Oberklasse von der Gnade der
Unterklasse lebt; und als er Darwin noch ein Mal las, konnte er nicht
leugnen, dass die Auslese, so wie sie jetzt war, alles andere als
natürlich sei. Aber das war nun einmal so, und das konnte man nicht
ändern, der Doktor und die Sozialisten mochten sagen, was sie
wollten.
Reformversuch

Sie hatte mit Ekel gesehen, wie die Mädchen zu Haushälterinnen für
ihre künftigen Männer erzogen wurden. Darum hatte sie eine
Fertigkeit gelernt, die sie unter allen Verhältnissen des Lebens
ernähren konnte. Sie machte Blumen.
Er hatte mit Schmerz gesehen, wie die Mädchen darauf warteten,
von ihren künftigen Männern versorgt zu werden; er wollte sich mit
einer freien, selbstständigen Frau verheiraten, die sich selber
ernähren konnte; dann würde er in ihr eine Seinesgleichen sehen
und eine Kameradin fürs Leben haben, keine Haushälterin.
Und das Schicksal wollte, dass sie sich trafen. Er war Maler, und
sie machte, wie gesagt, Blumen, und in Paris hatten sie diese neuen
Ideen bekommen.
Es war eine stilvolle Ehe. Sie hatten sich in Passy drei Zimmer
gemietet. Das Atelier lag in der Mitte, sein Zimmer auf der einen
Seite, ihr Zimmer auf der andern. Ein gemeinsames Bett wollten sie
nicht haben; das sei eine Schweinerei, die durchaus kein Gegenstück
in der Natur besitze und nur Übertreibung und Ausschweifung
veranlasse. Und sich im selben Zimmer entkleiden! Nein, jeder sein
eigenes Zimmer; und dann einen gemeinsamen neutralen Raum, das
Atelier. Keine Dienstboten; denn die Küche wollten sie gemeinsam
besorgen. Nur eine alte Frau, die morgens und abends kam.
Es war gut ausgerechnet, und es war ganz richtig gedacht.
– Wenn ihr aber Kinder bekommt? wandte der Zweifler ein.
– Wir werden keine Kinder bekommen!
Gut! Sie würden keine Kinder bekommen!
Es war entzückend! Er ging morgens auf den Markt und kaufte
ein. Darauf kochte er den Kaffee. Sie machte die Betten und räumte
die Zimmer auf. Dann setzten sie sich an die Arbeit.
Wenn sie müde wurden, plauderten sie eine Weile, gaben
einander einen guten Rat, lachten und waren sehr lustig.
Wenn der Mittag kam, machte er Feuer in der Küche, während sie
das Gemüse wusch. Er kochte Rindfleisch in der Brühe, während sie
zum Kaufmann hinunterlief; dann deckte sie, während er das Essen
auftischte.
Aber wie Geschwister lebten sie nicht. Sie sagten sich abends gute
Nacht, und jedes ging in sein Zimmer. Dann aber klopfte es an ihre
Tür und sie rief: herein! Doch das Bett war eng und es kam nie zu
Ausschweifungen, sondern jedes erwachte morgens im eigenen Bett.
Und dann klopfte er an die Wand:
– Guten Morgen, mein Mädchen! Wie steht es heute?
– Danke, gut; und dir?
Es war immer etwas Neues, wenn sie sich morgens trafen, und es
wurde nie alt.
Abends gingen sie oft zusammen aus und trafen mit Landsleuten
zusammen. Und sie wurde nicht geniert von Tabaksrauch, und sie
genierte auch selber nicht.
Das sei das Ideal einer Ehe, meinten die andern, ein so glückliches
Paar hätten sie noch nicht gesehen.
Aber das Mädchen hatte Eltern, die weit entfernt wohnten. Und
die schrieben und fragten unaufhörlich, ob Luise noch nicht guter
Hoffnung sei, denn sie sehnten sich nach einem Enkelkind. Luise
solle daran denken, dass die Ehe der Kinder und nicht der Eltern
wegen da sei. Das hielt Luise für eine altmodische Ansicht. Da fragte
die Mama, ob man denn mit den neuen Ideen die Absicht habe, das
Menschengeschlecht auszurotten. Daran habe Luise nicht gedacht,
und darum kümmere sie sich auch nicht. Sie sei glücklich und ihr
Mann auch, und jetzt habe die Welt endlich eine glückliche Ehe
gesehen, und darum sei die Welt neidisch.
Aber angenehm lebten sie. Keiner war der Herr des andern, und
zur Kasse schossen sie zusammen. Das eine Mal verdiente er mehr,
das andere Mal sie, aber das wurde unter einander ausgeglichen.
Und wenn sie Geburtstag hatten! Da erwachte sie davon, dass die
Aufwartefrau hereinkam mit einem Blumenstrauss und einem
Briefchen, auf das Blumen gemalt waren und in dem zu lesen stand:
– Der Frau Blumenknospe gratuliert ihr Anstreicher und ladet sie
zu einem feinen kleinen Frühstück ein – und zwar sofort!
Und dann klopfte es an seine Tür und dann – herein! Und sie
assen Frühstück auf dem Bett, auf seinem Bett; und die
Aufwartefrau arbeitete dann den ganzen Vormittag. Es war
entzückend.
Und nie ward es etwas Altes. Denn es dauerte zwei Jahre. Und
alle Weissager weissagten falsch.
So müsste die Ehe sein!
Dann aber geschah es, dass die Frau krank wurde. Sie glaubte, es
seien die Tapeten; er aber vermutete Bakterien. Ja, es waren
bestimmt Bakterien!
Aber es war auch etwas in Unordnung. Es war nicht so, wie es
sein sollte. Es war bestimmt eine Erkältung. Und dann wurde sie so
stark. Sollte es vielleicht ein Gewächs sein, von dem man soviel las?
Ja, es war bestimmt ein Gewächs. Sie ging zu einem Arzt. Als sie
nach Haus kam, weinte sie. Es war wirklich ein kleines Gewächs,
aber eins, das zu seiner Zeit ans Tageslicht kommen werde, um
Blume zu werden und Frucht anzusetzen.
Der Mann weinte nicht. Er fand Stil darin, und dann ging der
Lümmel in die Kneipe und prahlte noch damit. Aber die Frau weinte
wieder. Wie würde jetzt ihre Stellung zu ihm werden? Mit Arbeit
könne sie jetzt bald nichts mehr verdienen, und dann müsse sie sein
Brot essen. Und dann müssten sie sich eine Magd halten. Huh, diese
Mägde!
Alle Vorsorge, aller Vorbedacht, alle Voraussicht waren an dem
Unvermeidlichen gescheitert.
Aber die Schwiegermutter schrieb begeisterte Gratulationsbriefe
und wiederholte immer wieder, die Ehe sei von Gott der Kinder
wegen gestiftet, das Vergnügen der Eltern sei nur Nebensache.
Hugo beteuerte, sie brauche niemals daran zu denken, dass sie
nichts verdiene! Trage sie nicht mit ihrer Arbeit für sein Kind genug
zum Haushalt bei? Sei das nicht auch Geldeswert? Geld sei doch nur
Arbeit! Also bezahle sie ja auch ihr Teil.
Doch sie konnte es lange nicht verschmerzen, dass sie sein Brot
essen musste. Als aber das Kind kam, vergass sie alles. Und sie war
seine Frau und Kameradin wie früher, aber sie war ausserdem die
Mutter seines Kindes, und er fand, das sei das Beste von allem.
Naturhindernis

Ihr Vater hatte sie Buchführung lernen lassen, damit sie dem
gewöhnlichen Los der Mädchen entgehe: darauf zu warten, bis sie
geheiratet wird.
Sie war jetzt Buchführerin bei der Gepäckabteilung der
Eisenbahnen und wurde allgemein als tüchtig anerkannt. Sie wusste
die Leute zu behandeln, dass es eine Lust war, und sie hatte eine
schöne Zukunft vor sich.
Da kam der grüne Jäger von der Forstakademie, und sie
heirateten sich. Aber Kinder wollten sie nicht haben. Es sollte eine
geistige Ehe von der rechten Art werden, und die Welt sollte sehen,
dass die Frau auch ein seelisches Wesen und kein Weibchen sei.
Die beiden Gatten trafen sich mittags und nachts, und es war eine
wirkliche Ehe, die Verbindung zweier Seelen, und allerdings auch die
zweier Körper, aber davon sprach man natürlich nicht.
Eines Tages kam die Frau nach Hause und erzählte, die Dienstzeit
sei geändert. Ein neuer Nachtzug nach Malmö sei vom Reichstag
beschlossen worden, und sie habe künftig zwischen sechs und neun
Uhr abends Dienst. Das war ein Strich durch die Rechnung. Denn er
konnte nicht vor sechs Uhr nach Haus kommen. Unmöglich!
Jetzt musste jedes allein zu Mittag essen, und sie trafen sich nur
nachts. Er fand das etwas wenig. Und dann die langen Abende.
Er kam und holte sie ab. Es war ihm aber nicht angenehm, in der
Gepäckexpedition auf einem Stuhl zu sitzen und von den Trägern
gestossen zu werden. Er war immer im Wege. Und wenn er mit ihr,
die mit der Feder hinterm Ohr dasass, plaudern wollte, konnte sie
ihm das Wort abschneiden:
– Bitte, sei doch so lange still!
Dann wandten die Leute sich ab, und er konnte an ihren Rücken
sehen, dass sie grinsten.
Zuweilen wurde er von einem Buchhalter mit diesen Worten
angemeldet:
– Ihr Mann wartet auf Sie, Frau X.
„Ihr Mann“, das klang so geringschätzig.
Was ihn aber am meisten reizte, war, dass sie zum Nebenmann
am Pult einen jungen Laffen hatte, der ihr direkt in die Augen guckte
und sich oft, um ins Hauptbuch zu sehen, so über ihre Schulter
beugte, dass sein Kinn fast auf ihrer Brust lag! Und die beiden
sprachen von Fakturen und Zertifikaten; von Dingen, die alles
mögliche bedeuten konnten, denn er verstand sie nicht. Und sie
kollationierten zusammen und schienen vertrauter mit einander zu
sein, als Mann und Frau waren. Und das war sehr natürlich, denn sie
war mehr mit dem fröhlichen Laffen zusammen als mit ihrem Mann.
Er begann zu denken, es sei doch keine rechte geistige Ehe; damit
sie das sei, hätte er auch bei der Gepäckabteilung sein müssen. Jetzt
aber war er bei der Forstakademie.
Eines Tages, oder richtiger eines Nachts, verkündete sie, sie
müsse am nächsten Sonnabend die Versammlung der Eisenbahner
besuchen, die mit einem gemeinsamen Schmaus beschlossen würde.
Der Mann nahm die Mitteilung etwas verlegen auf.
– Du willst dahin gehen? war er naiv genug zu fragen.
– Welche Frage?
– Aber du bist die einzige Frau unter so vielen Männern, und wenn
Männer getrunken haben, werden sie roh!
– Besuchst du denn nicht Forsttage ohne mich?
– Allerdings, aber nicht als einziger Mann unter Frauen!
– Männer und Frauen seien doch gleich, und sie sei erstaunt, dass
er, der doch immer die Befreiung des Weibes gepredigt, etwas
dagegen habe, dass sie die Sitzung besuche!
– Er räume ein, es seien alte Vorurteile, die bei ihm noch
festsässen; er räume ein, sie habe recht und er habe unrecht, aber
er bitte sie, nicht hinzugehen: es sei ihm nun einmal unangenehm!
Er könne nicht davon loskommen!
– Das sei inkonsequent von ihm!
– Ja, es sei inkonsequent von ihm, aber es seien auch zehn
Generationen nötig, bis sich die Individuen da herausgearbeitet
hätten!
– Dann dürfe er auch nicht mehr Versammlungen besuchen.
– Das sei nicht dasselbe, denn dort seien nur Männer! Nicht dass
sie ohne ihn ausgehe, sei ihm unangenehm, sondern dass sie allein
mit so vielen Männern ausgehe!
– Allein würde sie nicht sein, denn die Frau des Kassierers werde
dabei sein als ...
– Als was?
– Als Frau des Kassierers!
– Dann könne er vielleicht mitgehen als „ihr Mann“!
– Warum wolle er sich demütigen, indem er lästig falle!
– Er wolle sich demütigen!
– Er sei eifersüchtig?
– Ja, warum nicht! Ihm sei bange, dass etwas zwischen sie
kommen könne.
– Pfui, er sei eifersüchtig, welche Kränkung! Welche
Beschimpfung, welches Misstrauen! Was denke er von ihr?
– Das Allerbeste! Er wolle es ihr beweisen: sie könne allein gehen!
– Sie dürfe also wirklich allein gehen! Wie gnädig!
Sie ging! Und kam erst gegen Morgen nach Haus, Sie musste
ihren Mann wecken und ihm erzählen! wie angenehm es gewesen
sei! Und wie es ihn freute, das zu hören! Sie hätten eine Rede auf
sie gehalten, und sie hätten Quartett gesungen und getanzt.
– Wie sei sie denn nach Haus gekommen?
– Herr Latte habe sie bis zur Haustür gebracht.
– Wenn nun ein Bekannter seine Frau um drei Uhr morgens am
Arm des Herrn Laffen getroffen hätte!
– Warum nicht! Sie habe doch keinen schlechten Ruf!
– Nein, aber sie könne einen bekommen!
– Ach, er sei eifersüchtig, und, was schlimmer sei, er sei neidisch!
Er gönne ihr kein Vergnügen. So sei es, wenn man verheiratet sei!
Wenn man ausgehe und sich amüsiere, kriege man Schelte, sobald
man nach Haus komme! Pfui, wie dumm die Ehe sei! Und sei es
überhaupt eine Ehe? Sie träfen sich nachts, ganz wie andere
Verheiratete. Und die Männer seien alle gleich. Höflich, bis sie sich
verheirateten, aber dann, dann! Ihr Mann sei gerade so, wie alle
anderen Männer: er glaube sie zu besitzen, sie zu beherrschen!
– Er habe geglaubt, ein Mal hätten sie gemeint, einander zu
besitzen, aber er habe sich geirrt. Sie besitze ihn, wie man einen
Hund besitze, dessen man immer sicher ist. Sei er etwas anderes als
ihr Diener, der sie abends abhole? Sei er etwas anderes als „ihr
Mann“? Aber wolle sie „seine Frau“ sein? Sei das Gleichstellung?
– Sie sei nicht nach Haus gekommen, um sich zu zanken. Sie wolle
immer seine Frau sein, und er solle immer ihr Männchen sein.
– Der Champagner wirkt! dachte er und drehte sich nach der
Wand.
Sie weinte und bat ihn, doch gerecht zu sein und ihr zu –
verzeihen.
Er verbarg sich unter der Decke.
Sie fragte noch ein Mal, ob er – ob er nicht wolle, dass sie seine
Frau sei.
– Doch, gewiss wolle er das! Aber er habe sich heute abend so
furchtbar gelangweilt, dass er nie mehr einen solchen Abend erleben
wolle.
– Aber das sollten sie jetzt vergessen!
Und sie vergassen es und sie war wieder sein Frauchen.
Am nächsten Abend, als der grüne Jäger seine Frau abholen
wollte, war sie in die Magazine gegangen. Er war allein im Kontor
und setzte sich auf ihren Stuhl. Da öffnet sich eine Glastür und Herr
Laffe steckt den Kopf herein:
– Annchen, bist du hier?
Nein, es war ihr Mann!
Er stand auf und ging seiner Wege! Herr Laffe nannte seine Anna
Annchen und duzte sie! Annchen! Das war zuviel.
Als sie nach Haus kam, gab es einen grossen Auftritt. Sie wies
dem grünen Jäger nach, seine Lehren von der Befreiung des Weibes
seien nicht ernst zu nehmen, da er es übel auffasse, wenn seine
Frau ihre Kameraden duze.
Das Schlimmste war, dass er zugab, seine Lehren seien nicht ernst
zu nehmen.
– Das sei nicht seine Meinung! Er ändere seine Ansichten! Was?
– Ja, freilich! Die Ansichten änderten sich nach der Wirklichkeit,
die so veränderlich sei! Habe er aber früher an eine geistige Ehe
geglaubt, so glaube er jetzt an gar keine Ehe mehr. Das sei ja ein
Fortschritt in radikaler Richtung! Und was das Geistige betreffe, so
sei sie jetzt geistig mehr mit Herrn Laffe verheiratet, dessen
Gedanken über Gepäckwesen sie täglich und stündlich teile, als mit
ihm, für dessen Forstkultur sie sich ganz und gar nicht interessiere!
Sei schliesslich ihre Ehe geistig? Sei sie so geistig!
– Nein, jetzt nicht mehr! Ihre Liebe sei tot! Er habe sie getötet, als
er den grossen Glauben an – die Befreiung des Weibes aufgegeben!
Es wurde immer giftiger, und der grüne Jäger suchte geistige Ehe
mit Forstmännern und gab das Gepäckwesen, das er nie verstanden
hatte, auf.
– Du verstehst mich nicht, wiederholte sie so oft!
– Nein, Gepäckwesen habe ich nicht gelernt, antwortete er.
Eines Nachts, oder richtiger eines Morgens, erzählte er, er müsse
mit einem Mädchenpensionat botanisieren gehen. Er lehre Botanik in
einem Mädchenpensionat.
So? Davon habe er ihr ja noch nichts gesagt! Grosse Mädchen?
– Kolossale! Sechzehn bis zwanzig Jahre alt!
– Hm! ... Am Vormittag?
– Nein, am Nachmittag! Und nachher würden sie draussen zu
Abend essen.
– Hm! Die Vorsteherin sei doch dabei?
– Nein! Aber sie habe volles Vertrauen zu ihm, da er verheiratet
sei! Es sei also zuweilen gut, verheiratet zu sein.
Am nächsten Tag war sie krank.
– Er könne doch nicht das Herz haben, sie zu verlassen?
– Der Dienst vor allem! Sei sie sehr krank?
– Oh, furchtbar!
Der Arzt wurde geholt, trotzdem sie es nicht wollte. Er erklärte, es
sei nicht gefährlich, der Mann könne gehen!
Gegen Morgen kam der grüne Jäger nach Haus! Wie lustig er war!
Und wie er sich amüsiert habe! Solch einen Tag habe er lange, lange
nicht erlebt!
Da brach es los: Huhuhuhu! Dieser Kampf sei ihr zu schwer! Und
er musste einen Eid ablegen, dass er nie eine andere als sie lieben
werde! Niemals!
Krämpfe und Weinessig!
Er war zu edelmütig, um von Einzelheiten des Schmauses mit den
Mädchen zu sprechen, aber er konnte es nicht lassen, das alte
Gleichnis von seinem Hundetum wieder vorzubringen, und er
erlaubte sich, sie darauf aufmerksam zu machen, dass zur Liebe der
Begriff Besitzrecht gehöre – auch von Seiten der Frau. Warum weine
sie denn? Über dasselbe, über das er fluchte, wenn sie mit zwanzig
Männern ausgehe! Die Furcht, ihn zu verlieren! Aber man verliert
nur, was man besitzt! Besitzt!
So wurde das Loch wieder geflickt. Aber die Gepäckabteilung und
das Mädchenpensionat standen mit ihren Scheren bereit und
schnitten wieder ab, was man angeheftet hatte. Eine harmonische
Ehe war es nicht mehr.
Da wurde die Frau krank!
Sie habe sich bestimmt an einem Gepäckstück im Magazin
verhoben. Sie sei so eifrig und könne es nicht leiden, wie die
Gepäckträger dastehen und auf sich warten lassen. Sie müsse immer
selber mit anfassen. Es sei sicher ein Bruch.
Es sei etwas Hartes zu fühlen, sagte die Hebamme.
Es war so weit! Wie böse sie wurde! Böse auf ihn, denn es sei
bestimmt nur Bosheit von ihm! Wie werde es ihr jetzt ergehen, mit
ihrer Zukunft. Sie müssten das Kind in ein Findelhaus geben. So
habe es Rousseau getan. Sonst sei der ja ein Dummkopf, aber in
diesem Punkt habe er recht.
Und so viel Launen! Der Jäger musste augenblicklich seine Botanik
im Mädchenpensionat aufgeben!
Aber das Schlimmste: sie konnte nicht mehr ins Magazin gehen.
Sie musste im Kontor sitzen und buchen. Und das Allerschlimmste:
sie erhielt einen Gehilfen, dessen geheime Aufgabe es war, sie zu
vertreten, wenn sie zu Haus bleiben musste.
Und die Kollegen waren nicht mehr wie früher. Und die Leute
grinsten. Sie hätte sich vor Scham verstecken mögen. Lieber sich in
ihrer Häuslichkeit verkriechen und das Essen kochen als hier wie ein
Spektakel sitzen. O welche Abgründe von Vorurteilen in den falschen
Herzen der Männer verborgen liegen.
Für den letzten Monat nahm sie Urlaub. Sie vermochte nicht mehr
vier Male am Tage den Weg zu machen. Und dann wurde sie hungrig
mitten am Vormittag und musste Butterbrote holen lassen. Und oft
war sie krank und musste eine Pause machen. Was für ein Leben!
Was für ein klägliches Los der Frau zugefallen war!
Und dann kam das Kind!
– Wollen wirs ins Findelhaus schicken? sagte der Jäger.
– Oh, er habe wohl kein Herz?
– Doch, das habe er!
Und das Kind blieb zu Hause!
Dann aber kam ein sehr höflicher Brief vom Betriebsamt und
fragte, wie es dem Frauchen gehe!
Es gehe ihr gut und sie könne übermorgen wieder Dienst tun.
Sie war schwach und musste einen Wagen nehmen. Aber sie
wurde bald wieder stark. Doch sie musste einen Laufburschen nach
Haus schicken, um zu fragen, wie es dem Kinde gehe; erst zwei Male
am Tage, dann alle zwei Stunden. Und als sie hörte, es habe
geschrien, wurde sie ganz wild und eilte nach Haus. Aber der Gehilfe
stand bereit, um sie zu vertreten. Die Vorgesetzten waren sehr
höflich und sagten nichts.
Eines Tages entdeckte die Frau, dass die Milch der Amme versiegt
war und dass die Person das nicht gemeldet habe, aus Furcht, ihre
Stelle zu verlieren. Sie nahm sofort Urlaub, um eine neue Amme zu
suchen! Ach, die waren sich alle gleich. Kein Interesse für fremde
Kinder, nur rohe Egoisten. Man konnte sich nie auf sie verlassen!
– Nein, sagte der Mann, in diesem Fall kann man sich nur auf sich
selber verlassen!
– Du meinst, ich soll meine Stellung aufgeben?
– Ich meine, du tust, was du willst!
– Und deine Sklavin werden!
– Nein, das meine ich durchaus nicht!
Der Kleine wurde krank, wie alle Kinder werden. Er kriegte Zähne!
Urlaub auf Urlaub. Das Kind bekam sogenanntes Zahnreissen!
Nachts wiegen, tagsüber Dienst, schläfrig, müde, unruhig, und dann
Urlaub. Der grüne Jäger war nett und trug das Kind nachts, sagte
aber nie etwas über die Stellung seiner Frau.
Doch sie kannte seine Gedanken. Er warte nur darauf, dass sie zu
Hause blieb; aber er sei falsch und darum schweige er! Wie falsch
die Männer seien! Sie hasse ihn; lieber würde sie sich töten, als ihre
Stelle aufgeben und seine Sklavin werden!
Der Jäger hatte jetzt vollständig jede Hoffnung aufgegeben, dass
sich die Frau von den Naturgesetzen emanzipieren könne; unter den
jetzigen Verhältnissen, war er klug genug, hinzuzufügen.
Als das Kind fünf Monate alt war, wurde die Frau wieder
schwanger.
Himmelkreuzdonnerwetter!
– Ja, wenn es ein Mal anfängt, dann ist der Teufel los!
Der Jäger musste seine Stellung im Mädchenpensionat wieder
übernehmen, um das Einkommen zu erhöhen, und jetzt – jetzt
streckte sie das Gewehr!
– Ich bin deine Sklavin, rief sie aus, als sie mit dem Abschied nach
Haus kam; ich bin deine Sklavin.
Nichtsdestoweniger leitet sie den Haushalt, und er liefert jeden
einzigen Pfennig unter ihre Schlüssel. Wenn er eine Zigarre haben
will, kommt er und hält eine lange Rede, ehe er seine Bitte
vorzubringen wagt. Sie verweigert es ihm nicht, niemals, aber er
findet es doch etwas lästig, um das Geld bitten zu müssen. Und
Sitzungen darf er besuchen, aber einen Schmaus nicht, und
Botanisieren mit Mädchen gibt es nicht mehr!
Er vermisst es auch nicht so sehr, denn er findet, das Beste ist, mit
den Kindern zu spielen!
Seine Kameraden sagen, er stehe unterm Pantoffel; doch darüber
lächelt er, indem er sagt, er befinde sich am besten dabei, denn sein
Weib sei eine sehr verständige und nette Frau.
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.

Let us accompany you on the journey of exploring knowledge and


personal growth!

ebookgate.com

You might also like