与SPSS的比较#
对于可能从SPSS迁移的用户,本页面旨在演示如何使用pandas执行各种SPSS操作。
如果您是 pandas 的新手,您可能需要先阅读10 分钟学会 pandas以熟悉该库。
按照惯例,我们如下导入 pandas 和 NumPy
In [1]: import pandas as pd
In [2]: import numpy as np
数据结构#
通用术语翻译#
pandas |
SPSS |
|---|---|
数据文件 |
|
列 |
变量 |
行 |
个案 |
groupby |
拆分文件 |
|
系统缺失值 |
DataFrame#
pandas中的DataFrame类似于SPSS的数据文件——一个二维数据源,具有不同类型的带标签列。如本文档所示,几乎所有在SPSS中可以进行的操作,在pandas中也都可以完成。
Series#
Series是代表DataFrame一列的数据结构。SPSS没有单独的单个变量数据结构,但总体而言,处理Series类似于处理SPSS中的变量。
Index#
每个DataFrame和Series都有一个Index——数据行的标签。SPSS没有完全对应的概念,因为个案只是从1开始顺序编号。在pandas中,如果未指定索引,则默认使用RangeIndex(第一行=0,第二行=1,依此类推)。
虽然使用带标签的Index或MultiIndex可以实现复杂的分析,并且最终是理解pandas的重要部分,但在本次比较中,我们将基本忽略Index,只将DataFrame视为一组列。请参阅索引文档以了解更多关于如何有效使用Index的信息。
副本与就地操作#
大多数 pandas 操作会返回 Series/DataFrame 的副本。要使更改“生效”,您需要将其分配给一个新变量
sorted_df = df.sort_values("col1")
或覆盖原始变量
df = df.sort_values("col1")
注意
您会发现某些方法提供了 inplace=True 或 copy=False 关键字参数
df.replace(5, inplace=True)
关于弃用和删除大多数方法的 inplace 和 copy(例如 dropna),除了极少数方法(包括 replace)之外,正在积极讨论中。在 Copy-on-Write 的上下文中,这两个关键字将不再是必需的。提案可以在这里找到。
数据输入/输出#
读取外部数据#
与SPSS一样,pandas提供了读取多种格式数据的工具。在后续的许多示例中将使用pandas测试中包含的tips数据集(csv)。
在SPSS中,您将使用“文件”>“打开”>“数据”导入CSV文件。
FILE > OPEN > DATA
/TYPE=CSV
/FILE='tips.csv'
/DELIMITERS=","
/FIRSTCASE=2
/VARIABLES=col1 col2 col3.
pandas中对应的操作将使用read_csv()。
url = (
"https://raw.githubusercontent.com/pandas-dev"
"/pandas/main/pandas/tests/io/data/csv/tips.csv"
)
tips = pd.read_csv(url)
tips
与SPSS的数据导入向导一样,read_csv可以接受多个参数来指定数据的解析方式。例如,如果数据是制表符分隔的,并且没有列名,pandas命令将是:
tips = pd.read_csv("tips.csv", sep="\t", header=None)
# alternatively, read_table is an alias to read_csv with tab delimiter
tips = pd.read_table("tips.csv", header=None)
数据操作#
过滤#
在SPSS中,筛选是通过“数据”>“选择个案”完成的。
SELECT IF (total_bill > 10).
EXECUTE.
在pandas中,可以使用布尔索引。
tips[tips["total_bill"] > 10]
排序#
在SPSS中,排序是通过“数据”>“排序个案”完成的。
SORT CASES BY sex total_bill.
EXECUTE.
在pandas中,这将被写成:
tips.sort_values(["sex", "total_bill"])
字符串处理#
查找字符串长度#
在SPSS中
COMPUTE length = LENGTH(time).
EXECUTE.
您可以使用 Series.str.len() 查找字符字符串的长度。在 Python 3 中,所有字符串都是 Unicode 字符串。len 包括尾随空格。使用 len 和 rstrip 来排除尾随空格。
In [3]: tips["time"].str.len()
Out[3]:
67 6
92 6
111 6
145 5
135 5
..
182 6
156 6
59 6
212 6
170 6
Name: time, Length: 244, dtype: int64
In [4]: tips["time"].str.rstrip().str.len()
Out[4]:
67 6
92 6
111 6
145 5
135 5
..
182 6
156 6
59 6
212 6
170 6
Name: time, Length: 244, dtype: int64
更改大小写#
在SPSS中
COMPUTE upper = UPCASE(time).
COMPUTE lower = LOWER(time).
EXECUTE.
等效的 pandas 方法是 Series.str.upper()、Series.str.lower() 和 Series.str.title()。
In [5]: firstlast = pd.DataFrame({"string": ["John Smith", "Jane Cook"]})
In [6]: firstlast["upper"] = firstlast["string"].str.upper()
In [7]: firstlast["lower"] = firstlast["string"].str.lower()
In [8]: firstlast["title"] = firstlast["string"].str.title()
In [9]: firstlast
Out[9]:
string upper lower title
0 John Smith JOHN SMITH john smith John Smith
1 Jane Cook JANE COOK jane cook Jane Cook
合并#
在SPSS中,合并数据文件是通过“数据”>“合并文件”完成的。
以下表格将用于合并示例
In [10]: df1 = pd.DataFrame({"key": ["A", "B", "C", "D"], "value": np.random.randn(4)})
In [11]: df1
Out[11]:
key value
0 A 0.469112
1 B -0.282863
2 C -1.509059
3 D -1.135632
In [12]: df2 = pd.DataFrame({"key": ["B", "D", "D", "E"], "value": np.random.randn(4)})
In [13]: df2
Out[13]:
key value
0 B 1.212112
1 D -0.173215
2 D 0.119209
3 E -1.044236
pandas DataFrame 有一个 merge() 方法,它提供了类似的功能。数据不必提前排序,并且可以通过 how 关键字实现不同的连接类型。
In [14]: inner_join = df1.merge(df2, on=["key"], how="inner")
In [15]: inner_join
Out[15]:
key value_x value_y
0 B -0.282863 1.212112
1 D -1.135632 -0.173215
2 D -1.135632 0.119209
In [16]: left_join = df1.merge(df2, on=["key"], how="left")
In [17]: left_join
Out[17]:
key value_x value_y
0 A 0.469112 NaN
1 B -0.282863 1.212112
2 C -1.509059 NaN
3 D -1.135632 -0.173215
4 D -1.135632 0.119209
In [18]: right_join = df1.merge(df2, on=["key"], how="right")
In [19]: right_join
Out[19]:
key value_x value_y
0 B -0.282863 1.212112
1 D -1.135632 -0.173215
2 D -1.135632 0.119209
3 E NaN -1.044236
In [20]: outer_join = df1.merge(df2, on=["key"], how="outer")
In [21]: outer_join
Out[21]:
key value_x value_y
0 A 0.469112 NaN
1 B -0.282863 1.212112
2 C -1.509059 NaN
3 D -1.135632 -0.173215
4 D -1.135632 0.119209
5 E NaN -1.044236
GroupBy操作#
拆分文件处理#
在SPSS中,拆分文件分析是通过“数据”>“拆分文件”完成的。
SORT CASES BY sex.
SPLIT FILE BY sex.
DESCRIPTIVES VARIABLES=total_bill tip
/STATISTICS=MEAN STDDEV MIN MAX.
pandas中的对应操作将是:
tips.groupby("sex")[["total_bill", "tip"]].agg(["mean", "std", "min", "max"])
缺失数据#
SPSS使用句点(.)表示数值缺失值,使用空格表示字符串缺失值。pandas使用NaN(非数字)表示数值缺失值,使用None或NaN表示字符串缺失值。
在 pandas 中,可以使用 Series.isna() 和 Series.notna() 来过滤行。
In [22]: outer_join[outer_join["value_x"].isna()]
Out[22]:
key value_x value_y
5 E NaN -1.044236
In [23]: outer_join[outer_join["value_x"].notna()]
Out[23]:
key value_x value_y
0 A 0.469112 NaN
1 B -0.282863 1.212112
2 C -1.509059 NaN
3 D -1.135632 -0.173215
4 D -1.135632 0.119209
pandas 提供了多种处理缺失数据的方法。以下是一些示例
删除包含缺失值的行#
In [24]: outer_join.dropna()
Out[24]:
key value_x value_y
1 B -0.282863 1.212112
3 D -1.135632 -0.173215
4 D -1.135632 0.119209
从前一行向前填充#
In [25]: outer_join.ffill()
Out[25]:
key value_x value_y
0 A 0.469112 NaN
1 B -0.282863 1.212112
2 C -1.509059 1.212112
3 D -1.135632 -0.173215
4 D -1.135632 0.119209
5 E -1.135632 -1.044236
用指定值替换缺失值#
使用平均值
In [26]: outer_join["value_x"].fillna(outer_join["value_x"].mean())
Out[26]:
0 0.469112
1 -0.282863
2 -1.509059
3 -1.135632
4 -1.135632
5 -0.718815
Name: value_x, dtype: float64
其他注意事项#
输出管理#
虽然pandas没有直接等同于SPSS的输出管理系统(OMS),但您可以通过多种方式捕获和导出结果。
# Save summary statistics to CSV
tips.groupby('sex')[['total_bill', 'tip']].mean().to_csv('summary.csv')
# Save multiple results to Excel sheets
with pd.ExcelWriter('results.xlsx') as writer:
tips.describe().to_excel(writer, sheet_name='Descriptives')
tips.groupby('sex').mean().to_excel(writer, sheet_name='Means by Gender')