跳转到内容

Pandas基础使用

参考:Learn Pandas | Kaggle

创建,读,写

创建数据框(DataFrame)和序列(Series)

import pandas as pd
# 创建一个数据框(DataFrame)`fruits`,像下面这样:
# +---+--------+---------+
# | | Apples | Bananas |
# +---+--------+---------+
# | 0 | 30 | 21 |
# +---+--------+---------+
fruits = pd.DataFrame({'Apples': [30], 'Bananas': [21]})
fruits2 = pd.DataFrame([[30, 21]], columns=['Apples', 'Bananas'])
print(fruits)
# 创建一个数据框(DataFrame)`fruits_sales`,像下面这样:
# +------------+--------+---------+
# | | Apples | Bananas |
# +------------+--------+---------+
# | 2017 Sales | 35 | 21 |
# | 2018 Sales | 41 | 34 |
# +------------+--------+---------+
fruit_sales = pd.DataFrame([[35, 21], [41, 34]], columns=['Apples', 'Bananas'], index=['2017 Sales', '2018 Sales'])
fruit_sales2 = pd.DataFrame({'Apples': [35, 41], 'Bananas': [21, 34]}, index=['2017 Sales', '2018 Sales'])
print(fruit_sales)
# 创建一个变量`ingredients`,指向一个 Series,像这样:
# Flour 4 cups
# Milk 1 cup
# Eggs 2 large
# Spam 1 can
# Name: Dinner, dtype: object
# 分析:该 Series 的名字是 Dinner,每一项都有索引,每一项是数量(quantities),索引是产品名(items)。
quantities = ['4 cups', '1 cup', '2 large', '1 can']
items = ['Flour', 'Milk', 'Eggs', 'Spam']
ingredients = pd.Series(quantities, index=items, name='Dinner')
ingredients

从文件读取数据

datas/winemag-data_first150k.csv
# 将葡萄酒评论(wine reviews)数据集(csv文件),读取为数据框,变量名为`reviews`
# 该 csv 文件首列是一列连续递增的整数,该列未命名,希望用这一列作为索引。提示: index_col 参数。
reviews = pd.read_csv("datas/winemag-data_first150k.csv", index_col=0)

保存数据到文件

# 保存数据框`animals`到一个csv文件,文件名:`cows_and_goats.csv`
animals = pd.DataFrame({'Cows': [12, 20], 'Goats': [22, 19]}, index=['Year 1', 'Year 2'])
animals.to_csv("cows_and_goats.csv")

索引,选择,赋值

import pandas as pd
reviews = pd.read_csv("datas/winemag-data-130k-v2.csv", index_col=0)
reviews.head(2) # 查看前两行
# 从 `reviews` 中选出(select)`description`列,赋值给变量`desc`
desc = reviews.description
desc = reviews["description"]
type(desc) # pandas.core.series.Series
# 选出(select)`reviews`的`description`列的第一个值,赋值给变量`first_description`
# 注意区分“索引”。
# python中,访问列表 a 中的第1个元素 a[0],0 称为下标,也可称为索引;
# pandas中,dataframe 或 series 有 index,也称为索引
# 为了区分,python中的索引称为“位置”或“索引位置”
# pandas中的索引称为“索引”或“索引标签”
# `iloc` uses the Python stdlib indexing scheme, where the first element of the range is included and the last one excluded. `loc`, meanwhile, indexes inclusively.
# This is particularly confusing when the DataFrame index is a simple numerical list, e.g. `0,...,1000`. In this case `df.iloc[0:1000]` will return 1000 entries, while `df.loc[0:1000]` return 1001 of them! To get 1000 elements using `loc`, you will need to go one lower and ask for `df.iloc[0:999]`.
first_description = reviews.description[0] # 0 是位置
first_description = reviews.description.iloc[0] # 同上,0 是位置
first_description = reviews.description.loc[0] # 0是索引标签,而不是位置
# 选出(select)`reviews`的第一行数据,赋值给变量`first_row`
first_row = reviews.iloc[0]
# 选出(select)`reviews`的`description`列的前 10 个值,赋值给变量`first_descriptions`
first_descriptions = reviews.description[:10]
first_descriptions = reviews.description.iloc[:10]
first_descriptions = reviews.description.head(10)
first_descriptions = reviews.loc[:9, 'description']
# 选出(select)`reviews`的索引标签(index labels)为 1,2,3,5,8 的数据(记录, records),赋值给变量`sample_reviews`
# 注意题目要求是选出:索引标签(index labels)为 1,2,3,5,8 的数据
# 注意是“索引标签”,因此应当使用 .loc,而不是 .iloc,.iloc用于根据位置索引选数据
indices = [1, 2, 3, 5, 8]
sample_reviews = reviews.loc[indices]
sample_reviews = reviews.loc[[1, 2, 3, 5, 8]]
# 创建一个新 DataFrame,名字为`df`,
# 包含 `reviews` 的 `country`, `province`, `region_1` 和 `region_2` 列,
# 以及索引标签(index labels)为 0, 1, 10, 100 的记录(records)
cols = ['country', 'province', 'region_1', 'region_2']
indices = [0, 1, 10, 100]
df = reviews.loc[indices, cols]
df = reviews.loc[[0,1,10,100], ["country", "province", "region_1", "region_2"]]
# 创建一个新 DataFrame,名字为`df`,
# 包含`reviews`中的前 100 条记录,`country`和`variety`列
df = reviews.loc[:99, ['country', 'variety']] # 注意 .loc这里的 99 是索引标签,指从索引0到索引99,包含索引99,共100个
df = reviews.iloc[:100, [0, 11]] # .iloc的索引与 python 的索引用法相同,左闭右开。`country`和`variety`列分别是第 0 列和第 11 列。
# 创建一个数据框`italian_wines`,包含`reviews`中关于产自`Italy`的酒的评论
# 提示:`reviews`的`country`列
italian_wines = reviews.loc[reviews.country == "Italy"]
italian_wines = reviews[reviews.country == "Italy"]
# 创建一个数据框`top_oceania_wines`,包含所有这些酒的评论:
# 至少 95 分(points),(满分100)
# 产自澳大利亚(Australia)或新西兰(New Zealand)
top_oceania_wines = reviews[((reviews.country == "Australia") | (reviews.country == "New Zealand")) & (reviews.points >= 95)]
top_oceania_wines = reviews.loc[reviews.country.isin(["Australia", "New Zealand"]) & (reviews.points >= 95)]

汇总和映射

import pandas as pd
reviews = pd.read_csv("datas/winemag-data-130k-v2.csv", index_col=0)
# 数据框`reviews`的`points`列的中位数(median)是多少?
median_points = reviews.points.median()
# 数据集中都有哪些国家?(不要包含重复值)
countries = reviews.country.unique()
# 各个国家在数据集中各出现多少次?创建一个 series `reviews_per_country`,映射 国家名称 到 该国家的葡萄酒评论的数量
reviews_per_country = reviews.country.value_counts()
# 创建一个变量`centered_price`,包含处理后的`price`列的数据,处理方法是:价格 减去 价格平均值
# 注,这种中心(centering)变换(transformation)是在应用各种机器学习算法之前的一个常见的处理步骤
centered_price = reviews.price - reviews.price.mean()
# 我是一个比较在乎“性价比”的葡萄酒买家。买哪种葡萄酒最划算(best bargain)?
# 创建一个变量`bargain_wine`,值为最具“性价比”的酒的`title`,
# “最具性价比”的判断方法:找 分数(points)和价格(price)的比值 的最大者。
# 提示:`.idxmax()`方法
bargain_idx = (reviews.points / reviews.price).idxmax()
bargain_wine = reviews.loc[bargain_idx, 'title']
# 当描述一瓶葡萄酒时,你能用的词汇是有限的。葡萄酒更加的 "tropical" 还是更加的 "fruity"?
# 创建一个 Series 对象`descriptor_counts`,计算数据集中`description`列中这两个词汇出现的次数。
# (为简单起见,忽略这些词汇的大写版本。)
# 提示:使用 map 函数检查每个 description 中是否包含字符串"tropical",然后计算出现 True 的次数。对"fruity"也重复这个操作。最后,创建一个Series对象,将这两个值合并起来。
descriptor_counts = pd.Series((reviews.description.str.contains('tropical').sum(), reviews.description.str.contains('fruity').sum()), index=['tropical', 'fruity'])
n_trop = reviews.description.map(lambda desc: "tropical" in desc).sum()
n_fruity = reviews.description.map(lambda desc: "fruity" in desc).sum()
descriptor_counts = pd.Series([n_trop, n_fruity], index=['tropical', 'fruity'])
# 我们想要在网站上展示这些葡萄酒评论,但是一个从 80 到 100 分的评分系统理解起来太复杂了
# 我们想要将它们转换成简单的星级评分。95分及以上的分数算作3星,85分及以上但少于95分的算作2星。其他任何分数算作1星。
# 此外,加拿大葡萄酒生产商协会在网站上购买了大量广告,所以任何来自加拿大的葡萄酒都应自动获得3星,无论得分如何。
# 创建一个名为 `star_ratings` 的 Series 对象,其中包含数据集中每条评论对应的星级数。
star_ratings = reviews.apply(lambda row: 3 if row['points'] >= 95 or row['country'] == 'Canada' else 2 if row['points'] >= 85 else 1, axis='columns')
def stars(row):
if row.country == 'Canada':
return 3
elif row.points >= 95:
return 3
elif row.points >= 85:
return 2
else:
return 1
star_ratings = reviews.apply(stars, axis='columns')

分组和排序

import pandas as pd
reviews = pd.read_csv("datas/winemag-data-130k-v2.csv", index_col=0)
# 谁是数据集中评论数最多的葡萄酒评论者?创建一个Series对象`reviews_written`,其索引是数据集中的 `taster_twitter_handle`列,其值是每个人写的评论数。
reviews_written = reviews.groupby("taster_twitter_handle").taster_twitter_handle.count()
reviews_written = reviews.groupby('taster_twitter_handle').size()
# 给定金额下,我能购买到多好的葡萄酒?创建一个 Series 对象`best_rating_per_price`,其索引是葡萄酒价格`price`,其值是评论中该价格的葡萄酒的最高得分。
# 按价格升序排序(因此4.0位于顶部,3300.0位于底部)。
best_rating_per_price = reviews.groupby("price").points.max().sort_index(ascending=True)
best_rating_per_price = reviews.groupby('price')['points'].max().sort_index()
# 每种葡萄酒的最低和最高价格是多少?创建一个DataFrame对象`price_extremes`,其索引是数据集中的品种类别`variety`,其值是最小值和最大值。
price_extremes = reviews.groupby("variety").price.agg(['min', 'max'])
# price_extremes = reviews.groupby('variety').price.agg([min, max]) # 即将淘汰
# 什么品种的葡萄酒最贵?创建一个名为 `sorted_varieties` 的变量,其包含前一个问题中的 DataFrame 的副本,根据最低价格和最高价格降序排序(以打破平局)。
# sorted_varieties = price_extremes.copy().sort_values(by=['min', 'max'], ascending=False)
sorted_varieties = price_extremes.sort_values(by=['min', 'max'], ascending=False)
# 创建一个Series对象,其索引是评论者,其值是该评论者给出的平均评分。
# 提示:`taster_name`和`points`列。
reviewer_mean_ratings = reviews.groupby("taster_name").points.mean()
# 各个评论者给出的平均评分是否有显著差异?使用`describe()`方法查看值范围的摘要。
reviewer_mean_ratings.describe()
# 哪些国家和品种的组合在评论中最多?创建一个Series对象`country_variety_counts`,其索引是`{country, variety}`对组成的`MultiIndex`。
# 例如,美国产的 pinot noir 应映射到`{"US", "Pinot Noir"}`。
# 根据葡萄酒数量按降序排序Series中的值。
country_variety_counts = reviews.groupby(["country", "variety"]).size().sort_values(ascending=False)

数据类型和缺失值

import pandas as pd
reviews = pd.read_csv("datas/winemag-data-130k-v2.csv", index_col=0)
# 数据集中 points 列的数据类型是什么?
# 提示:dtype是DataFrame或Series的属性之一
dtype = reviews.points.dtype
# 创建一个Series对象,其中的数据来自 points 列,但将数据转换为字符串。
# 提示:在原生Python中,字符串是str类型。
# 提示:使用 `.astype()` 将一种类型的列转换为另一种类型。
point_strings = reviews.points.map(lambda x: str(x))
point_strings = reviews.points.astype(str)
# 有时 price 列是 null。数据集中有多少评论缺少价格?
n_missing_prices = pd.isnull(reviews.price).sum()
n_missing_prices = reviews.price.isnull().sum()
missing_price_reviews = reviews[reviews.price.isnull()]
n_missing_prices = len(missing_price_reviews)
# 哪些地区产葡萄酒最多?
# 创建一个Series对象`reviews_per_region`,计算 region_1 字段中每个值出现的次数。
# 由于该字段通常缺少数据,所以用"Unknown"替换缺失的值。按降序排序。
# 你的输出应该类似于:
"""
Unknown 21247
Napa Valley 4480
...
Bardolino Superiore 1
Primitivo del Tarantino 1
Name: region_1, Length: 1230, dtype: int64
"""
# 提示:使用 fillna(), value_counts() 和 sort_values()
reviews.region_1 = reviews.region_1.fillna("Unknown")
reviews_per_region = reviews.groupby("region_1").size().sort_values(ascending=False)
reviews_per_region = reviews.region_1.fillna('Unknown').value_counts().sort_values(ascending=False)

重命名和组合(combining)

import pandas as pd
reviews = pd.read_csv("datas/winemag-data-130k-v2.csv", index_col=0)
# region_1 和 region_2 作为数据集中的 地点列(locale columns) 来说,命名不够具有信息性(pretty uninformative names)。
# 创建一个 reviews 的副本,并将这些列重命名为 region 和 locale。
# 提示:使用 rename()函数,并指定 columns 参数。
renamed = reviews.rename(columns={"region_1": "region", "region_2": "locale"})
renamed = reviews.rename(columns=dict(region_1='region', region_2='locale'))
# 将数据集`reviews`的索引的名称设置为 wines。
# 提示:使用 rename_axis() 方法
reindexed = reviews.rename_axis("wines", axis='rows')
# Things on Reddit 数据集包括 reddit.com 上一些排名靠前的论坛("subreddits")中的产品链接。
# 运行下面的代码加载在 /r/gaming 子论坛上提及的产品(products)的数据框,
# 以及另一个数据框,其中包含在 /r/movies 子论坛上提到的产品。
gaming_products = pd.read_csv("../input/things-on-reddit/top-things/top-things/reddits/g/gaming.csv")
gaming_products['subreddit'] = "r/gaming"
movie_products = pd.read_csv("../input/things-on-reddit/top-things/top-things/reddits/m/movies.csv")
movie_products['subreddit'] = "r/movies"
# 创建一个数据框`combined_products`,其中包含在两个子论坛上提到的所有产品。
# 提示:使用 pd.concat()
combined_products = pd.concat([gaming_products, movie_products])
# Kaggle上的 Powerlifting Database 数据集包括一个举重比赛的 CSV 表格和一个举重选手的表格。
# 运行下面的代码将这些数据集加载到数据框中:
powerlifting_meets = pd.read_csv("../input/powerlifting-database/meets.csv")
powerlifting_competitors = pd.read_csv("../input/powerlifting-database/openpowerlifting.csv")
# 这两个表格都包含 MeetID,MeetID是每个比赛(竞赛)的唯一键(unique key)。
# 根据这一信息,生成一个将两个表格合并成一个的数据集`powerlifting_combined`。
left = powerlifting_meets.set_index("MeetID")
right = powerlifting_competitors.set_index("MeetID")
powerlifting_combined = left.join(right)
powerlifting_combined = powerlifting_meets.set_index("MeetID").join(powerlifting_competitors.set_index("MeetID"))