空值处理
dropna()
删除包含空值的行
默认情况下,dropna()
会删除包含任何空值的行。
import pandas as pd
import numpy as np
# 创建一个包含空值的DataFrame
df = pd.DataFrame({
'A': [1, np.nan, 3],
'B': [4, 5, np.nan],
'C': [7, 8, 9]
})
# 删除包含空值的行
df_dropped_rows = df.dropna()
print(df_dropped_rows)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
在这个例子中,第二行和第三行都包含空值,但由于默认设置是删除包含空值的任何行,所以这两行都会被删除。然而,由于第三行在’B’列中有空值,而第二行在’A’列中有空值,且没有其他行在所有列中都非空,因此结果将是一个空DataFrame(在这个特定例子中)。
如果你想要删除包含空值的特定列的行,你可以使用subset
参数。
# 只考虑'A'列和'B'列中的空值来删除行
df_dropped_rows_subset = df.dropna(subset=['A', 'B'])
print(df_dropped_rows_subset)
- 1
- 2
- 3
- 4
在这个修改后的例子中,只有第二行会因为’A’列中的空值而被删除。
删除包含空值的列
如果你想删除包含空值的列,你需要将axis
参数设置为1(或'columns'
)。
# 删除包含空值的列
df_dropped_columns = df.dropna(axis=1)
print(df_dropped_columns)
- 1
- 2
- 3
- 4
在这个例子中,'B’列会被删除,因为它包含空值。
设置删除空值的阈值
你可以使用thresh
参数来指定一个阈值,只有当行或列中的非空值数量少于这个阈值时,才会被删除。
# 删除非空值少于2个的行
df_dropped_rows_thresh = df.dropna(thresh=2)
print(df_dropped_rows_thresh)
- 1
- 2
- 3
- 4
在这个例子中,第二行会被删除,因为它只有1个非空值。
防止就地修改
与drop()
方法类似,dropna()
默认返回一个新的DataFrame,而不会修改原始DataFrame。如果你希望直接修改原始DataFrame,可以使用inplace=True
参数。
df.dropna(inplace=True)
print(df) # 此时,原始DataFrame已被修改
- 1
- 2
fillna()
在Pandas中,fillna
方法用于填充 DataFrame 或 Series 中的缺失值(即 NaN 值)。它提供了多种选项来指定要填充的值或方法。以下是一些常用的用法示例:
基本用法
用单个值填充
import pandas as pd
import numpy as np
# 创建一个包含 NaN 值的 DataFrame
df = pd.DataFrame({
'A': [1, 2, np.nan, 4],
'B': [np.nan, 2, 3, 4],
'C': [1, np.nan, np.nan, 4]
})
# 用单个值填充所有 NaN
df_filled = df.fillna(0)
print(df_filled)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
用不同的值填充不同列
# 用字典指定每列要填充的值
df_filled_diff = df.fillna({'A': 0, 'B': 1, 'C': 2})
print(df_filled_diff)
- 1
- 2
- 3
用前一个有效值填充(前向填充)
# 使用前一个有效值填充
df_filled_ffill = df.fillna(method='ffill')
print(df_filled_ffill)
- 1
- 2
- 3
用后一个有效值填充(后向填充)
# 使用后一个有效值填充
df_filled_bfill = df.fillna(method='bfill')
print(df_filled_bfill)
- 1
- 2
- 3
用列的均值填充
# 使用列的均值填充 NaN 值
df_filled_mean = df.fillna(df.mean())
print(df_filled_mean)
- 1
- 2
- 3
用插值法填充
# 使用插值法填充(线性插值)
df_filled_interpolate = df.interpolate()
print(df_filled_interpolate)
- 1
- 2
- 3
注意事项
fillna
方法返回一个新的 DataFrame 或 Series,不会修改原始数据。- 可以使用
inplace=True
参数直接修改原始数据,例如df.fillna(0, inplace=True)
。 method='ffill'
和method='bfill'
分别对应于前向填充和后向填充,适用于时间序列数据。- 插值法(
interpolate
)通常用于处理时间序列数据中的缺失值。
判断DataFrame为空
检查形状(shape)
通过检查 DataFrame
的形状(即行数和列数),可以判断它是否为空。如果行数为0或列数为0,则可以认为它是空的。
import pandas as pd
# 创建一个空的 DataFrame
df = pd.DataFrame()
# 判断 DataFrame 是否为空
if df.shape[0] == 0 or df.shape[1] == 0:
print("DataFrame is empty")
else:
print("DataFrame is not empty")
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
使用 empty
属性
Pandas 的 DataFrame
对象有一个 empty
属性,它直接返回一个布尔值,指示 DataFrame
是否为空(即没有任何行)。注意,这个属性只检查行数,不检查列数。因此,如果一个 DataFrame
有列但没有行,它仍然会被认为是空的。
import pandas as pd
# 创建一个空的 DataFrame
df = pd.DataFrame()
# 判断 DataFrame 是否为空
if df.empty:
print("DataFrame is empty")
else:
print("DataFrame is not empty")
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
结合使用 shape
和 empty
如果你希望更严格地检查 DataFrame
是否既没有行也没有列,可以结合使用 shape
和 empty
属性。
import pandas as pd
# 创建一个空的 DataFrame
df = pd.DataFrame()
# 判断 DataFrame 是否为空(既没有行也没有列)
if df.empty and df.shape[1] == 0:
print("DataFrame is completely empty (no rows and no columns)")
else:
print("DataFrame is not completely empty")
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
检查数据内容
在某些情况下,你可能还需要检查 DataFrame
中的数据内容是否为 NaN
或其他特定值。不过,这通常用于更复杂的场景,而不是简单地判断 DataFrame
是否为空。
import pandas as pd
import numpy as np
# 创建一个全是 NaN 的 DataFrame
df = pd.DataFrame(np.nan, index=[0], columns=[0])
# 判断 DataFrame 是否真正“内容为空”(即所有值都是 NaN)
if df.isnull().values.all():
print("DataFrame has no non-NaN values")
else:
print("DataFrame has non-NaN values")
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
重复值
duplicated()
在 Pandas 中,duplicated()
是一个非常实用的方法,用于标识重复的行。它返回一个布尔值的 Series
,标识哪些行是重复的,默认情况下标识除了第一次出现的所有重复行。
duplicated()
方法的基本用法:
DataFrame.duplicated(subset=None, keep='first')
- 1
参数说明:
-
subset:用于判断重复的列。如果没有指定,默认会检查所有列。
-
keep
:控制哪一条记录被标记为重复:
'first'
(默认):标记除了第一次出现的记录外,其他重复的行。'last'
:标记除了最后一次出现的记录外,其他重复的行。False
:标记所有重复的行(包括第一次和最后一次)。
返回值:
duplicated()
返回一个布尔类型的 Series
,标记哪些行是重复的。True
表示该行是重复的,False
表示该行是第一次出现。
例子:
假设有一个包含重复数据的 DataFrame
:
import pandas as pd
# 示例数据
data = {
'id': [1, 2, 2, 3, 4, 4, 5],
'name': ['Alice', 'Bob', 'Bob', 'Charlie', 'David', 'David', 'Eve'],
'age': [25, 30, 30, 35, 40, 40, 45]
}
df = pd.DataFrame(data)
print(df)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
输出:
id name age
0 1 Alice 25
1 2 Bob 30
2 2 Bob 30
3 3 Charlie 35
4 4 David 40
5 4 David 40
6 5 Eve 45
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
示例 1:标记重复的行(默认 keep='first'
)
# 使用 duplicated() 查找重复的行
duplicates = df.duplicated()
print(duplicates)
- 1
- 2
- 3
- 4
输出:
0 False
1 False
2 True
3 False
4 False
5 True
6 False
dtype: bool
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 解释:
duplicated()
会标记除第一次出现的记录之外的所有重复记录。返回的布尔值Series
表示哪些行是重复的,True
表示是重复的行,False
表示是第一次出现的行。 - 例如,
id=2
和id=4
的行是重复的,所以下标为 2 和 5 的行会被标记为True
。
示例 2:标记最后一次出现的重复记录(keep='last'
)
# 使用 duplicated() 查找重复的行,但保留最后一次出现的记录
duplicates_last = df.duplicated(keep='last')
print(duplicates_last)
- 1
- 2
- 3
- 4
输出:
0 False
1 False
2 True
3 False
4 False
5 True
6 False
dtype: bool
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 解释:
keep='last'
时,duplicated()
会标记除了最后一次出现的记录外,其他重复记录为True
。所以,id=2
和id=4
的第二次出现会被标记为True
,而第一次出现会标记为False
。
示例 3:标记所有重复记录(keep=False
)
# 使用 duplicated() 查找所有的重复行,包括第一次和最后一次
duplicates_all = df.duplicated(keep=False)
print(duplicates_all)
- 1
- 2
- 3
- 4
输出:
0 False
1 True
2 True
3 False
4 True
5 True
6 False
dtype: bool
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 解释:
keep=False
时,duplicated()
会标记所有的重复记录为True
,包括第一次出现的记录。
示例 4:根据特定列判断重复项
# 使用 'id' 列来判断重复
duplicates_subset = df.duplicated(subset=['id'])
print(duplicates_subset)
- 1
- 2
- 3
- 4
输出:
0 False
1 False
2 True
3 False
4 False
5 True
6 False
dtype: bool
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 解释:
subset=['id']
表示只根据id
列来判断重复项。id=2
和id=4
会被标记为重复,第二次出现时标记为True
,第一次出现时标记为False
。
示例 5:删除重复行(基于 duplicated()
)
你可以使用 duplicated()
来标记重复项,然后结合 DataFrame
的布尔索引删除重复项。例如,要删除所有重复的行,保留第一次出现的记录:
df_no_duplicates = df[~df.duplicated()]
print(df_no_duplicates)
- 1
- 2
- 3
输出:
id name age
0 1 Alice 25
1 2 Bob 30
3 3 Charlie 35
4 4 David 40
6 5 Eve 45
- 1
- 2
- 3
- 4
- 5
- 6
- 解释:
~df.duplicated()
返回的是duplicated()
布尔Series
的反向值,~True
是False
,~False
是True
,因此通过df[~df.duplicated()]
可以保留第一次出现的记录,删除后续的重复行。
示例 6:修改原始 DataFrame
(使用 inplace=True
)
df.drop_duplicates(inplace=True)
print(df)
- 1
- 2
- 3
- 解释:
drop_duplicates()
会修改原始的DataFrame
,删除重复行。
总结:
-
duplicated()
方法用于标记重复行,返回一个布尔值Series
,表示哪些行是重复的。 -
keep
- 1
参数可以控制保留哪一条记录:
'first'
(默认):标记除了第一次出现的记录外,其他重复行。'last'
:标记除了最后一次出现的记录外,其他重复行。False
:标记所有重复的行,包括第一次和最后一次出现的行。
-
subset
参数允许你只根据特定的列来判断重复项。 -
结合
duplicated()
和布尔索引,可以删除重复的行。
drop_duplicates()
在 Pandas 中,drop_duplicates()
是一个非常实用的函数,用于去除重复的行(或列)。它允许你根据特定的列或整个数据框来删除重复项。
drop_duplicates()
方法的基本用法:
DataFrame.drop_duplicates(subset=None, keep='first', inplace=False, ignore_index=False)
- 1
参数说明:
-
subset:指定哪些列用于判断重复。如果没有指定,默认情况下会根据所有列判断重复。
-
keep
:决定保留哪一条重复记录:
'first'
(默认):保留首次出现的记录,删除后续的重复项。'last'
:保留最后一条记录,删除之前的重复项。False
:删除所有重复项。
-
inplace:是否在原始数据上进行修改。如果为
True
,则会直接修改原始DataFrame
,并返回None
;如果为False
(默认),则返回一个新的DataFrame
。 -
ignore_index:是否重新索引。默认为
False
,如果为True
,则会重新排列索引。
例子:
假设有一个包含重复数据的 DataFrame
:
import pandas as pd
# 示例数据
data = {
'id': [1, 2, 2, 3, 4, 4, 5],
'name': ['Alice', 'Bob', 'Bob', 'Charlie', 'David', 'David', 'Eve'],
'age': [25, 30, 30, 35, 40, 40, 45]
}
df = pd.DataFrame(data)
print(df)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
输出:
id name age
0 1 Alice 25
1 2 Bob 30
2 2 Bob 30
3 3 Charlie 35
4 4 David 40
5 4 David 40
6 5 Eve 45
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
示例 1:去除所有重复的行(基于所有列)
df_no_duplicates = df.drop_duplicates()
print(df_no_duplicates)
- 1
- 2
- 3
输出:
id name age
0 1 Alice 25
1 2 Bob 30
3 3 Charlie 35
4 4 David 40
6 5 Eve 45
- 1
- 2
- 3
- 4
- 5
- 6
- 解释:默认情况下,
drop_duplicates()
会检查所有列的重复项,并删除后面的重复行,只保留第一条出现的记录。
示例 2:根据某一列去重(例如:根据 id
列)
df_no_duplicates = df.drop_duplicates(subset=['id'])
print(df_no_duplicates)
- 1
- 2
- 3
输出:
id name age
0 1 Alice 25
1 2 Bob 30
3 3 Charlie 35
4 4 David 40
6 5 Eve 45
- 1
- 2
- 3
- 4
- 5
- 6
- 解释:
subset=['id']
表示根据id
列来检查重复项。重复的id=2
和id=4
被删除,只保留每个id
的第一次出现。
示例 3:保留最后一次出现的重复记录
df_no_duplicates = df.drop_duplicates(subset=['id'], keep='last')
print(df_no_duplicates)
- 1
- 2
- 3
输出:
id name age
0 1 Alice 25
2 2 Bob 30
3 3 Charlie 35
5 4 David 40
6 5 Eve 45
- 1
- 2
- 3
- 4
- 5
- 6
- 解释:通过
keep='last'
,我们选择保留重复项中最后一次出现的记录。
示例 4:删除所有重复的行(不保留任何重复项)
df_no_duplicates = df.drop_duplicates(subset=['id'], keep=False)
print(df_no_duplicates)
- 1
- 2
- 3
输出:
id name age
0 1 Alice 25
3 3 Charlie 35
6 5 Eve 45
- 1
- 2
- 3
- 4
- 解释:
keep=False
表示删除所有重复的记录,包括第一次出现的记录。因此,只有没有重复的行被保留下来。
示例 5:修改原始 DataFrame
(使用 inplace=True
)
df.drop_duplicates(subset=['id'], keep='first', inplace=True)
print(df)
- 1
- 2
- 3
输出:
id name age
0 1 Alice 25
1 2 Bob 30
3 3 Charlie 35
4 4 David 40
6 5 Eve 45
- 1
- 2
- 3
- 4
- 5
- 6
- 解释:使用
inplace=True
后,drop_duplicates()
会直接在原始df
上进行修改,而不是返回一个新的DataFrame
。
示例 6:重新索引
df_no_duplicates = df.drop_duplicates(subset=['id'], keep='first', ignore_index=True)
print(df_no_duplicates)
- 1
- 2
- 3
输出:
id name age
0 1 Alice 25
1 2 Bob 30
2 3 Charlie 35
3 4 David 40
4 5 Eve 45
- 1
- 2
- 3
- 4
- 5
- 6
- 解释:使用
ignore_index=True
后,删除重复行后会重新排列索引,从0
开始。
总结:
drop_duplicates()
是一个非常实用的方法,可以帮助你快速清理重复的数据。subset
参数允许你根据指定的列来判断是否为重复数据。keep
参数控制保留哪一条记录:'first'
(默认)、'last'
或False
(删除所有重复项)。- 使用
inplace=True
可以直接修改原始DataFrame
,而不是返回一个新的DataFrame
。
数据融合/拼接
merge()
关键字
-
left:第一个 DataFrame 对象。
-
right:第二个 DataFrame 对象。
-
how:指定合并的方式。默认为 ‘inner’。其他选项包括 ‘left’, ‘right’, ‘outer’。
-
‘inner’:内连接,只返回两个对象中都存在的键的交集。
-
‘left’:左连接,返回左对象中的所有键,以及右对象中匹配的键。
-
‘right’:右连接,返回右对象中的所有键,以及左对象中匹配的键。
-
‘outer’:外连接,返回左和右对象中所有的键,匹配不到的键则填充 NaN。
-
-
on:要加入的列名。必须在左右 DataFrame 对象中都存在。如果未指定,且未指定
left_on
和right_on
,则 DataFrame 中的列名交集将被作为连接键。 -
left_on:左 DataFrame 中的列或索引级别名称用作键。可以是列名、索引名或长度的数组。
-
right_on:右 DataFrame 中的列或索引级别名称用作键。可以是列名、索引名或长度的数组。
-
left_index:布尔值,默认为 False。如果为 True,则使用左 DataFrame 的索引(行标签)作为其连接键。
-
right_index:布尔值,默认为 False。如果为 True,则使用右 DataFrame 的索引(行标签)作为其连接键。
-
sort:布尔值,默认为 False。根据连接键对合并后的数据进行排序。这在合并具有大量数据的大型 DataFrame 时可能会非常耗时。
-
suffixes:用于追加到重叠列名末尾的元组字符串(默认为 (‘_x’, ‘_y’))。例如,如果两个对象都有 ‘A’ 列,则结果对象将有 ‘A_x’ 和 ‘A_y’ 列。
-
copy:布尔值,默认为 True。如果为 False,则不复制数据(可能节省内存)。
-
indicator:布尔值或字符串,默认为 False。如果为 True 或字符串,将向输出 DataFrame 添加一个特殊列 ‘_merge’,以指示每行数据的来源:‘left_only’、‘right_only’ 或 ‘both’。如果为字符串,则将该字符串用作列名。
-
validate:检查合并键是否在左右 DataFrame 对象中指定为列名。可以是 ‘one_to_one’, ‘one_to_many’, ‘many_to_one’, ‘many_to_many’ 之一。仅在合并键在 DataFrame 中明确指定时才有意义(即使用
on
、left_on
或right_on
参数)。
示例1:内连接(Inner Join)
import pandas as pd
# 创建两个示例DataFrame
df1 = pd.DataFrame({
'key': ['A', 'B', 'C', 'D'],
'value1': [1, 2, 3, 4]
})
df2 = pd.DataFrame({
'key': ['A', 'B', 'E', 'F'],
'value2': [5, 6, 7, 8]
})
# 内连接
merged_inner = pd.merge(df1, df2, on='key', how='inner')
print(merged_inner)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
输出:
key value1 value2
0 A 1 5
1 B 2 6
- 1
- 2
- 3
示例2:左连接(Left Join)
# 左连接
merged_left = pd.merge(df1, df2, on='key', how='left')
print(merged_left)
- 1
- 2
- 3
输出:
key value1 value2
0 A 1 5.0
1 B 2 6.0
2 C 3 NaN
3 D 4 NaN
- 1
- 2
- 3
- 4
- 5
示例3:右连接(Right Join)
# 右连接
merged_right = pd.merge(df1, df2, on='key', how='right')
print(merged_right)
- 1
- 2
- 3
输出:
key value1 value2
0 A 1.0 5
1 B 2.0 6
2 E NaN 7
3 F NaN 8
- 1
- 2
- 3
- 4
- 5
示例4:外连接(Outer Join)
# 外连接
merged_outer = pd.merge(df1, df2, on='key', how='outer')
print(merged_outer)
- 1
- 2
- 3
输出:
key value1 value2
0 A 1.0 5.0
1 B 2.0 6.0
2 C 3.0 NaN
3 D 4.0 NaN
4 E NaN 7.0
5 F NaN 8.0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
示例5:使用left_on和right_on参数
# 创建两个示例DataFrame,其中用于合并的列名不同
df3 = pd.DataFrame({
'lkey': ['A', 'B', 'C'],
'lvalue': [10, 20, 30]
})
df4 = pd.DataFrame({
'rkey': ['A', 'B', 'D'],
'rvalue': [40, 50, 60]
})
# 使用left_on和right_on参数进行合并
merged_custom_keys = pd.merge(df3, df4, left_on='lkey', right_on='rkey', how='inner')
print(merged_custom_keys)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
输出:
lkey lvalue rkey rvalue
0 A 10 A 40
1 B 20 B 50
- 1
- 2
- 3
示例6:使用suffixes参数
# 创建两个示例DataFrame,其中有一列名称相同
df5 = pd.DataFrame({
'key': ['X', 'Y', 'Z'],
'value': [100, 200, 300]
})
df6 = pd.DataFrame({
'key': ['X', 'Y', 'W'],
'value': [400, 500, 600]
})
# 使用suffixes参数为相同名称的列添加后缀
merged_suffixes = pd.merge(df5, df6, on='key', suffixes=('_left', '_right'), how='inner')
print(merged_suffixes)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
输出:
key value_left value_right
0 X 100 400
1 Y 200 500
- 1
- 2
- 3
这些示例展示了如何使用pandas.merge()
函数进行不同类型的数据合并,包括内连接、左连接、右连接、外连接,以及如何处理不同名称的合并键和相同名称的列。
concat()
在Pandas中,concat
函数是一个非常强大的工具,用于将多个pandas对象(如DataFrame或Series)沿着指定轴拼接在一起。这个函数非常灵活,允许你沿着行(axis=0,默认)或列(axis=1)进行拼接,并且可以通过多种方式处理索引和列标签。
以下是pd.concat
函数的一些关键参数和用法示例:
关键参数
- objs:要拼接的对象列表或字典。列表中的元素可以是DataFrame、Series或其他pandas对象。如果是字典,则字典的键会被用作结果的列名或行索引。
- axis:拼接的轴。0表示沿着行拼接(纵向),1表示沿着列拼接(横向)。默认值为0。
- join:指定如何处理索引。‘outer’(默认)表示取并集,'inner’表示取交集。
- ignore_index:如果为True,则不保留原有的索引,而是生成一个新的整数索引。
- keys:用于添加多级索引(层次化索引)。这个参数通常与字典一起使用。
- levels:用于多级索引(层次化索引)的级别名称。
- names:多级索引(层次化索引)的名称。
- verify_integrity:如果为True,则在拼接时检查新生成的DataFrame的索引/列是否有重复。这有助于捕捉潜在的错误。
用法示例
1. 沿着行拼接两个DataFrame
import pandas as pd
df1 = pd.DataFrame({'A': ['A0', 'A1'], 'B': ['B0', 'B1']})
df2 = pd.DataFrame({'A': ['A2', 'A3'], 'B': ['B2', 'B3']})
result = pd.concat([df1, df2], axis=0)
print(result)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
2. 沿着列拼接两个DataFrame
df1 = pd.DataFrame({'A': ['A0', 'A1'], 'B': ['B0', 'B1']})
df2 = pd.DataFrame({'C': ['C0', 'C1'], 'D': ['D0', 'D1']})
result = pd.concat([df1, df2], axis=1)
print(result)
- 1
- 2
- 3
- 4
- 5
3. 使用字典拼接,并添加多级索引
df1 = pd.DataFrame({'A': ['A0', 'A1'], 'B': ['B0', 'B1']})
df2 = pd.DataFrame({'A': ['A2', 'A3'], 'B': ['B2', 'B3']})
result = pd.concat({'key1': df1, 'key2': df2}, axis=0, keys=['group1', 'group2'])
print(result)
- 1
- 2
- 3
- 4
- 5
在这个例子中,我们使用了keys
参数来添加一个新的层次化索引,使得结果DataFrame有两个索引级别:一个是我们指定的键(‘group1’和’group2’),另一个是原有的索引。
4. 忽略原有索引,生成新的整数索引
df1 = pd.DataFrame({'A': ['A0', 'A1'], 'B': ['B0', 'B1']}, index=[1, 2])
df2 = pd.DataFrame({'A': ['A2', 'A3'], 'B': ['B2', 'B3']}, index=[3, 4])
result = pd.concat([df1, df2], axis=0, ignore_index=True)
print(result)
- 1
- 2
- 3
- 4
- 5
在这个例子中,ignore_index=True
使得结果DataFrame使用了新的从0开始的整数索引。
顺序错乱值
sort_values()
在pandas
中,sort_values()
是一个用于对DataFrame
或Series
按指定列进行排序的方法。它允许你按升序或降序排列数据。
用法
DataFrame.sort_values(by, axis=0, ascending=True, inplace=False, kind='quicksort', na_position='last', ignore_index=False)
- 1
参数说明
by
: 用于排序的列名称或列名的列表。对于DataFrame
,这是你希望依据其值来排序的列。axis
: 默认值为0,表示按行排序。如果为1,表示按列排序。ascending
: 布尔值或布尔值列表,默认为True
,表示按升序排序。如果为False
,则按降序排序。如果是一个列表,长度应与by
的长度相同,用于不同列的排序顺序。inplace
: 默认为False
,表示返回一个新的排序后的DataFrame
,如果设为True
,则原地修改,不返回新对象。kind
: 排序算法,支持'quicksort'
(快速排序)、'mergesort'
(归并排序)和'heapsort'
(堆排序)。默认为'quicksort'
。na_position
: 默认为'last'
,表示缺失值排在最后。如果设为'first'
,缺失值将排在最前面。ignore_index
: 默认为False
,表示保留原来的索引。如果设为True
,返回排序后的结果时,重新生成索引。
示例
1. 按单列排序
import pandas as pd
df = pd.DataFrame({
'A': [3, 1, 4, 2],
'B': [7, 8, 5, 6]
})
# 按列 'A' 升序排序
df_sorted = df.sort_values(by='A')
print(df_sorted)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
输出:
A B
1 1 8
3 2 6
0 3 7
2 4 5
- 1
- 2
- 3
- 4
- 5
2. 按多列排序
# 按 'A' 升序,'B' 降序排序
df_sorted = df.sort_values(by=['A', 'B'], ascending=[True, False])
print(df_sorted)
- 1
- 2
- 3
输出:
A B
1 1 8
3 2 6
0 3 7
2 4 5
- 1
- 2
- 3
- 4
- 5
3. 原地排序(不返回新的DataFrame
)
df.sort_values(by='A', inplace=True)
print(df)
- 1
- 2
输出:
A B
1 1 8
3 2 6
0 3 7
2 4 5
- 1
- 2
- 3
- 4
- 5
4. 排序时处理缺失值
df_with_nan = pd.DataFrame({
'A': [3, 1, 4, None],
'B': [7, 8, None, 6]
})
# 按 'A' 升序排序,缺失值排在最后
df_sorted = df_with_nan.sort_values(by='A', na_position='last')
print(df_sorted)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
输出:
A B
1 1.0 8.0
0 3.0 7.0
2 4.0 NaN
3 NaN 6.0
- 1
- 2
- 3
- 4
- 5
注意
sort_values()
是对数据进行排序并返回排序后的数据,而不改变原始的DataFrame
(除非inplace=True
)。- 对于
Series
,sort_values()
可以直接作用在数据上。
sort_index()
在pandas
中,sort_index()
是一个用于根据行或列的索引对DataFrame
或Series
进行排序的方法。它的主要作用是按照索引的顺序对数据进行排序,而不是按照数据的值进行排序。
用法
DataFrame.sort_index(axis=0, ascending=True, inplace=False, kind='quicksort', na_position='last', ignore_index=False)
- 1
参数说明
axis
: 默认为0
,表示按照行索引进行排序。如果为1
,则表示按列索引排序。ascending
: 布尔值或布尔值列表,默认True
。表示是否按升序排序。如果为False
,则按降序排序。如果是一个列表,长度应该和索引的数量一致,用于不同索引的排序顺序。inplace
: 默认为False
,表示返回一个排序后的DataFrame
。如果设为True
,则对原始数据进行排序,不返回新对象。kind
: 排序算法,支持'quicksort'
(快速排序)、'mergesort'
(归并排序)和'heapsort'
(堆排序)。默认为'quicksort'
。na_position
: 默认为'last'
,表示缺失值排在最后。如果设为'first'
,缺失值会排在最前面。ignore_index
: 默认为False
,表示保留原有的索引。如果设为True
,会重新生成索引。
示例
1. 按行索引排序
import pandas as pd
df = pd.DataFrame({
'A': [3, 1, 4, 2],
'B': [7, 8, 5, 6]
}, index=['d', 'a', 'c', 'b'])
# 按行索引升序排序
df_sorted = df.sort_index()
print(df_sorted)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
输出:
A B
a 1 8
b 2 6
c 4 5
d 3 7
- 1
- 2
- 3
- 4
- 5
2. 按列索引排序
# 按列索引升序排序
df_sorted = df.sort_index(axis=1)
print(df_sorted)
- 1
- 2
- 3
输出:
A B
d 3 7
a 1 8
c 4 5
b 2 6
- 1
- 2
- 3
- 4
- 5
3. 降序排序索引
# 按行索引降序排序
df_sorted = df.sort_index(ascending=False)
print(df_sorted)
- 1
- 2
- 3
输出:
A B
d 3 7
c 4 5
b 2 6
a 1 8
- 1
- 2
- 3
- 4
- 5
4. 原地排序(不返回新的DataFrame
)
df.sort_index(inplace=True)
print(df)
- 1
- 2
输出:
A B
a 1 8
b 2 6
c 4 5
d 3 7
- 1
- 2
- 3
- 4
- 5
5. 排序时处理缺失值
df_with_nan = pd.DataFrame({
'A': [3, 1, 4, None],
'B': [7, 8, None, 6]
}, index=['d', 'a', 'c', 'b'])
# 按行索引排序,并将缺失值放到最后
df_sorted = df_with_nan.sort_index(na_position='last')
print(df_sorted)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
输出:
A B
a 1.0 8.0
b NaN 6.0
c 4.0 NaN
d 3.0 7.0
- 1
- 2
- 3
- 4
- 5
6. 忽略原有索引,重新生成索引
# 忽略原有索引,重新生成索引
df_sorted = df_with_nan.sort_index(ignore_index=True)
print(df_sorted)
- 1
- 2
- 3
输出:
A B
0 1.0 8.0
1 NaN 6.0
2 4.0 NaN
3 3.0 7.0
- 1
- 2
- 3
- 4
- 5
总结
sort_index()
主要是根据索引进行排序,而不是根据数据本身的值。- 可以选择按行索引或列索引进行排序,支持升序和降序排列。
- 通过设置
inplace=True
,可以原地修改DataFrame
。 - 处理缺失值时,可以使用
na_position
来决定缺失值的位置。
rank()
在 pandas
中,rank()
方法用于对 DataFrame
或 Series
中的数值进行排名。根据所提供的参数,可以控制排名的计算方式,支持多种排名方法,如 升序 或 降序,以及 相同值的排名 方式。
基本用法
DataFrame.rank(axis=0, method='average', ascending=True, na_option='keep', numeric_only=False, pct=False)
- 1
参数解释
-
axis
: 默认为0
,表示对行进行排名。如果为1
,则对列进行排名。 -
- 排名方法。可选值有:
method
'average'
: 相同数值的平均排名(默认)。'min'
: 相同数值的最小排名。'max'
: 相同数值的最大排名。'first'
: 按照原始顺序进行排名,遇到相同数值时,先出现的排前面。'dense'
: 稠密排名,相同数值的排名相同,接下来的排名没有空缺。
-
ascending
: 布尔值,默认为True
,表示升序排序。如果为False
,则按降序排序。 -
na_option
: 控制缺失值的处理方式。可选值为'keep'
、'top'
、'bottom'
。默认为'keep'
,即保留缺失值不参与排名。'top'
和'bottom'
分别表示将缺失值排在前面或最后。 -
numeric_only
: 默认为False
,表示包括所有类型的列进行排名。如果为True
,则仅考虑数值类型的列。 -
pct
: 默认为False
,表示返回的排名为整数。如果为True
,返回的排名是比例值(百分比形式)。
示例
1. 基本排名(默认 average
)
import pandas as pd
data = {'score': [3.5, 4.0, 3.65, 3.85, 4.0, 3.65]}
df = pd.DataFrame(data)
df['rank'] = df['score'].rank()
print(df)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
输出:
score rank
0 3.50 4.0
1 4.00 1.5
2 3.65 3.5
3 3.85 2.0
4 4.00 1.5
5 3.65 3.5
- 1
- 2
- 3
- 4
- 5
- 6
- 7
解释:
- 使用
average
排名方法,相同的分数(如 4.0 和 3.65)的排名为相同的平均值。例如,4.0 出现了两次,所以它们的排名是1.5
。
2. 使用 min
排名方法
df['rank_min'] = df['score'].rank(method='min')
print(df)
- 1
- 2
输出:
score rank rank_min
0 3.50 4.0 4.0
1 4.00 1.5 1.0
2 3.65 3.5 3.0
3 3.85 2.0 2.0
4 4.00 1.5 1.0
5 3.65 3.5 3.0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
解释:
- 使用
min
方法时,所有相同的分数都获得最小排名。例如,4.0 的排名是1
,3.65 的排名是3
,即便它们出现多次。
3. 使用 dense
排名方法
df['rank_dense'] = df['score'].rank(method='dense')
print(df)
- 1
- 2
输出:
score rank rank_min rank_dense
0 3.50 4.0 4.0 4.0
1 4.00 1.5 1.0 1.0
2 3.65 3.5 3.0 3.0
3 3.85 2.0 2.0 2.0
4 4.00 1.5 1.0 1.0
5 3.65 3.5 3.0 3.0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
解释:
dense
方法给相同的分数相同的排名,并且排名没有跳跃。例如,两个分数相同(如 4.0 和 3.65)的排名相同,但接下来的排名没有空缺。
4. 排名方法 first
df['rank_first'] = df['score'].rank(method='first')
print(df)
- 1
- 2
输出:
score rank rank_min rank_dense rank_first
0 3.50 4.0 4.0 4.0 4.0
1 4.00 1.5 1.0 1.0 1.0
2 3.65 3.5 3.0 3.0 3.0
3 3.85 2.0 2.0 2.0 2.0
4 4.00 1.5 1.0 1.0 1.0
5 3.65 3.5 3.0 3.0 3.0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
解释:
first
方法按照出现的顺序进行排名。当有相同分数时,先出现的分数获得较小的排名。
5. 排名计算百分比(pct=True
)
df['rank_pct'] = df['score'].rank(pct=True)
print(df)
- 1
- 2
输出:
score rank rank_min rank_dense rank_first rank_pct
0 3.50 4.0 4.0 4.0 4.0 0.833333
1 4.00 1.5 1.0 1.0 1.0 0.166667
2 3.65 3.5 3.0 3.0 3.0 0.5
3 3.85 2.0 2.0 2.0 2.0 0.333333
4 4.00 1.5 1.0 1.0 1.0 0.166667
5 3.65 3.5 3.0 3.0 3.0 0.5
- 1
- 2
- 3
- 4
- 5
- 6
- 7
解释:
pct=True
返回百分比排名,即每个分数的排名占所有分数的比例。排名越高的分数比例越小,接近 0。
总结
rank()
是一个非常灵活的工具,用于根据不同的规则为数据中的每个元素分配排名。- 常见的排名方法包括
average
(默认)、min
、max
、dense
和first
,它们决定了相同值的排名如何计算。 - 可以通过设置
ascending=False
来进行降序排名,pct=True
返回排名的百分比。
数据的移动
shift()
shift() 函数是 Pandas 库中的一个数据处理函数,用于将数据按指定方向移动或偏移。它可以对时间序列数据或其他类型的数据进行操作,通常用于计算时间序列数据的差值、百分比变化等。该函数的主要作用是将数据移动到指定的行或列,留下空白或填充 NaN 值。
shift() 函数的语法
shift() 函数的基本语法如下:
DataFrame.shift(periods=1, freq=None, axis=0, fill_value=None)
参数说明:
-
periods:指定移动的步数,可以为正数(向下移动)或负数(向上移动)。默认为 1。
-
freq:可选参数,用于指定时间序列数据的频率,通常用于时间序列数据的移动操作。
-
axis:指定移动的方向,可以为 0(默认,沿行移动)或 1(沿列移动)。
-
fill_value:可选参数,用于填充移动后留下的空白位置,通常为填充 NaN 值。
shift() 函数的示例
通过一些示例来演示 shift() 函数的用法。
示例 1:向下移动数据
import pandas as pd
data = {'A': [1, 2, 3, 4, 5],
'B': [10, 20, 30, 40, 50]}
df = pd.DataFrame(data)
- 1
- 2
- 3
- 4
- 5
向下移动一行数据
df_shifted = df.shift(periods=1)
print(df_shifted)
输出结果:
A B
0 NaN NaN
1 1.0 10.0
2 2.0 20.0
3 3.0 30.0
4 4.0 40.0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
在这个示例中,创建了一个包含两列数据的 DataFrame,并使用 shift() 函数向下移动了一行数据。移动后,第一行的数据被填充为 NaN。
示例 2:向上移动数据
import pandas as pd
data = {'A': [1, 2, 3, 4, 5],
'B': [10, 20, 30, 40, 50]}
df = pd.DataFrame(data)
- 1
- 2
- 3
- 4
- 5
向上移动一行数据
df_shifted = df.shift(periods=-1)
print(df_shifted)
输出结果:
A B
0 2.0 20.0
1 3.0 30.0
2 4.0 40.0
3 5.0 50.0
4 NaN NaN
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
这个示例,使用负数的 periods 参数将数据向上移动了一行。最后一行的数据被填充为 NaN。
示例 3:向右移动列数据
import pandas as pd
data = {'A': [1, 2, 3, 4, 5],
'B': [10, 20, 30, 40, 50]}
df = pd.DataFrame(data)
- 1
- 2
- 3
- 4
- 5
向右移动一列数据
df_shifted = df.shift(periods=1, axis=1)
print(df_shifted)
输出结果:
A B
0 NaN 1.0
1 NaN 2.0
2 NaN 3.0
3 NaN 4.0
4 NaN 5.0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
在这个示例中,使用 axis=1 参数将列数据向右移动了一列,左边填充为 NaN。
示例 4:指定填充值
import pandas as pd
data = {'A': [1,
2, 3, 4, 5],
'B': [10, 20, 30, 40, 50]}
df = pd.DataFrame(data)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
向下移动一行数据,填充空白处为 0
df_shifted = df.shift(periods=1, fill_value=0)
print(df_shifted)
输出结果:
A B
0 0 0
1 1 10
2 2 20
3 3 30
4 4 40
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
在这个示例中,使用 fill_value 参数指定了填充值为 0,因此移动后的空白位置被填充为 0。
日期类型应用
Timedelta()
pandas.Timedelta
是 Pandas 库中的一个类,用于表示时间跨度或持续时间。它通常用于表示两个日期或时间之间的差异,或者进行日期、时间的加减运算。
Timedelta
的常见用途:
- 表示时间间隔:例如一天、两小时、三分钟等。
- 日期时间运算:例如,计算一个日期与另一个日期的差异,或者将某个时间单位添加到日期上。
Timedelta
组件:
- days:天数。
- hours:小时数。
- minutes:分钟数。
- seconds:秒数。
- milliseconds:毫秒数。
- microseconds:微秒数。
- nanoseconds:纳秒数。
创建 Timedelta
对象:
你可以通过多种方式创建 Timedelta
对象:
import pandas as pd
# 通过字符串创建 Timedelta
timedelta1 = pd.Timedelta('1 days') # 1 天
timedelta2 = pd.Timedelta('5 hours') # 5 小时
timedelta3 = pd.Timedelta('2 minutes') # 2 分钟
# 通过整数和单位创建 Timedelta
timedelta4 = pd.Timedelta(days=1) # 1 天
timedelta5 = pd.Timedelta(hours=5) # 5 小时
timedelta6 = pd.Timedelta(minutes=10) # 10 分钟
# 通过多个单位创建 Timedelta
timedelta7 = pd.Timedelta(weeks=1, days=2, hours=3, minutes=4) # 1 周 2 天 3 小时 4 分钟
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
Timedelta
的常见操作:
加减时间:
你可以将 Timedelta
对象加到一个 datetime
对象上,或者从中减去。
# 当前时间
now = pd.to_datetime('2024-01-01')
# 加 5 天
new_date = now + pd.Timedelta(days=5)
print(new_date) # 输出:2024-01-06
# 减 2 小时
new_time = now - pd.Timedelta(hours=2)
print(new_time) # 输出:2023-12-31 22:00:00
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
计算两个日期或时间之间的差异:
你可以通过直接相减两个 datetime
对象来计算时间差异,结果是一个 Timedelta
对象。
# 两个时间
date1 = pd.to_datetime('2024-01-01')
date2 = pd.to_datetime('2024-01-06')
# 计算差异
timedelta = date2 - date1
print(timedelta) # 输出:5 days 00:00:00
- 1
- 2
- 3
- 4
- 5
- 6
- 7
Timedelta
对象进行运算:
# 创建一个 Timedelta 对象
delta = pd.Timedelta(days=2, hours=3)
# 输出 Timedelta 对象的各个部分
print(delta.days) # 2
print(delta.seconds) # 10800 秒(3 小时 = 3 * 3600 秒)
print(delta.total_seconds()) # 177600 秒 (2 天 3 小时的总秒数)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
示例:用 Timedelta
计算前一天日期
如果你想利用 Timedelta
来比较日期并确保日期是连续的(例如,确保没有跳过的日期),你可以用 Timedelta
来加减日期,确保前后日期是连续的。
例如,假设你有一个日期列,并希望找出温度比前一天高的记录。
示例代码:
import pandas as pd
# 示例数据
data = {
'id': [1, 2],
'recordDate': ['2000-12-14', '2000-12-16'],
'temperature': [3, 5]
}
# 创建 DataFrame
df = pd.DataFrame(data)
# 将 'recordDate' 列转换为日期格式并排序
df['recordDate'] = pd.to_datetime(df['recordDate'])
df = df.sort_values('recordDate')
# 获取前一天的温度
df['previous_temperature'] = df['temperature'].shift(1)
df['previous_recordDate'] = df['recordDate'].shift(1)
# 使用 Timedelta 来检查日期是否是前一天
df['is_previous_day'] = df['recordDate'] == (df['previous_recordDate'] + pd.Timedelta(days=1))
# 筛选出温度比前一天高的记录,且日期是连续的(前后日期相差 1 天)
result = df[(df['temperature'] > df['previous_temperature']) & df['is_previous_day']]['id']
# 输出结果
print(result)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
解释:
- 日期转换:将
recordDate
列转换为日期格式,并按日期排序。 - 前一天比较:通过
shift(1)
获取前一天的日期和温度。 - 日期差检查:用
pd.Timedelta(days=1)
确保前一天的日期是连续的。 - 筛选符合条件的结果:确保温度比前一天高,并且日期是连续的。
输出结果:
less
Series([], Name: id, dtype: int64)
- 1
- 2
- 3
- 4
- 5
解释:
由于 2000-12-14
和 2000-12-16
之间没有 2000-12-15
,所以没有连续的日期,最终返回空结果。
总结:
Timedelta
主要用于表示时间差,支持加减运算,并可以方便地进行日期时间之间的比较和计算。- 在日期比较时,
Timedelta
可以帮助我们确保前后日期是连续的,从而避免出现日期跳跃的问题。
DateOffset()
DateOffset是pandas库中用于处理日期时间偏移量的类。它允许你以不同的时间单位(如天、小时、分钟等)来移动日期时间。
特点:
- 支持多种时间单位:天、小时、分钟等。
- 遵循日历规则,适用于处理如工作日、月末等复杂偏移。
使用方法:
- 创建一个DateOffset对象,指定偏移的时间单位和数量。
- 将DateOffset对象与日期时间相加或相减,实现偏移。
示例:
import pandas as pd
# 创建一个日期
date = pd.Timestamp('2023-01-01')
# 创建一个DateOffset对象,表示一天的偏移
offset = pd.DateOffset(days=1)
# 应用偏移
new_date = date + offset
print(new_date) # 输出:2023-01-02 00:00:00
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
注意事项:
- 确保时间单位与DateOffset对象的参数相匹配。
- 处理时区信息时,确保时区正确处理。
frame类型数据更新
在 pandas
中将一条数据更新到一个 DataFrame
中,可以有几种不同的方法,取决于你是要 添加新行 还是 更新已有行。
方法 1: 添加新行
如果你想将一条新数据(新行)添加到 DataFrame
中,可以使用 pd.DataFrame.append()
或 pd.concat()
方法。这两种方法都可以用来将新的数据添加到现有的 DataFrame
中。
示例 1: 使用 append()
假设你有一个现有的 DataFrame
和你要添加的一行数据:
import pandas as pd
# 示例 DataFrame
df = pd.DataFrame({
'id': [1, 2, 3],
'num': ['A', 'B', 'C']
})
# 要插入的新行
new_row = {'id': 4, 'num': 'D'}
# 使用 append() 添加新行
df = df.append(new_row, ignore_index=True)
# 打印结果
print(df)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
输出:
id num
0 1 A
1 2 B
2 3 C
3 4 D
- 1
- 2
- 3
- 4
- 5
说明:
append()
方法会返回一个新的DataFrame
,所以需要将返回结果重新赋值给df
。ignore_index=True
表示重新生成索引。
示例 2: 使用 concat()
concat()
是一种更灵活的方法,也可以用于添加新行。我们可以通过将新的数据转换为一个单行的 DataFrame
并与原 DataFrame
合并来实现。
# 将新行转换为 DataFrame
new_row_df = pd.DataFrame({'id': [4], 'num': ['D']})
# 使用 concat() 添加新行
df = pd.concat([df, new_row_df], ignore_index=True)
# 打印结果
print(df)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
输出:
id num
0 1 A
1 2 B
2 3 C
3 4 D
- 1
- 2
- 3
- 4
- 5
方法 2: 更新已有行
如果你要根据某些条件来更新 DataFrame
中的已有行数据,可以直接通过行索引进行更新。例如,假设我们想更新 id
为 2 的行的 num
值。
示例 3: 更新已有行的数据
# 假设我们要更新 id 为 2 的行
df.loc[df['id'] == 2, 'num'] = 'Updated Value'
# 打印结果
print(df)
- 1
- 2
- 3
- 4
- 5
输出:
id num
0 1 A
1 2 Updated Value
2 3 C
3 4 D
- 1
- 2
- 3
- 4
- 5
说明:
df.loc[df['id'] == 2, 'num']
用于选择id
为 2 的行的num
列,然后直接将其值更新为'Updated Value'
。
方法 3: 通过索引位置更新
如果你知道要更新的数据行的索引,可以直接通过 iloc[]
来访问并更新该行。
示例 4: 通过索引位置更新数据
# 假设我们要更新索引为 1 的行
df.iloc[1, df.columns.get_loc('num')] = 'Updated Again'
# 打印结果
print(df)
- 1
- 2
- 3
- 4
- 5
输出:
id num
0 1 A
1 2 Updated Again
2 3 C
3 4 D
- 1
- 2
- 3
- 4
- 5
方法 4: 批量更新
如果你需要根据某些条件批量更新多行数据,可以使用 apply()
或 where()
等方法。
示例 5: 使用 apply()
批量更新
# 假设我们根据 'id' 列的值来更新 'num' 列
df['num'] = df['id'].apply(lambda x: 'Updated' if x == 2 else 'Not Updated')
# 打印结果
print(df)
- 1
- 2
- 3
- 4
- 5
输出:
id num
0 1 Not Updated
1 2 Updated
2 3 Not Updated
3 4 Not Updated
- 1
- 2
- 3
- 4
- 5
示例 6: 使用 update()
批量更新
DataFrame.update()
方法的作用是用另一个 DataFrame
或 Series
来更新当前 DataFrame
中的值。更新时,源数据(other
)的索引和列索引会与目标数据进行对比,如果匹配,则更新目标数据的对应位置。
update()
方法的参数
-
other
:另一个DataFrame
或Series
,用于提供要更新的值。 -
join
控制如何对齐索引和列。可以是'left'
、'right'
、'outer'
或'inner'
,默认是'left'
。'left'
:使用other
中的索引和列进行更新(保留目标DataFrame
的索引和列)。'right'
:使用目标DataFrame
中的索引和列进行更新。'outer'
:合并两个DataFrame
的所有索引和列,任何一个DataFrame
中缺失的部分将填充NaN
。'inner'
:只使用两个DataFrame
中都有的索引和列。 -
overwrite
:布尔值,默认是True
。如果为True
,则将目标DataFrame
中的所有值都更新为源DataFrame
中的对应值。否则,只会更新那些原数据中为NaN
的位置。
update()
示例
示例 1:基本使用
import pandas as pd
# 原始 DataFrame
df1 = pd.DataFrame({
'A': [1, 2, 3, 4],
'B': [5, 6, 7, 8],
'C': [9, 10, 11, 12]
})
# 更新数据的 DataFrame
df2 = pd.DataFrame({
'A': [10, 20],
'B': [50, 60],
'C': [15, 25]
}, index=[1, 2])
# 使用 update() 更新 df1
df1.update(df2)
print(df1)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
输出:
A B C
0 1 5 9
1 20 50 15
2 20 60 25
3 4 8 12
- 1
- 2
- 3
- 4
- 5
说明:
- 在
df1
中,索引为 1 和 2 的行被df2
中相应的值替换了。 df1
中其他位置的值(如索引为 0 和 3 的行)没有被df2
中的任何值更新,因为df2
中没有这些位置的数据。
示例 2:使用 join
参数
通过 join
参数,可以控制如何对齐索引和列。如果 join='left'
,那么将保留 df1
的索引,并使用 df2
中的值进行更新。
df1.update(df2, join='left')
print(df1)
- 1
- 2
输出:
A B C
0 1 5 9
1 20 50 15
2 20 60 25
3 4 8 12
- 1
- 2
- 3
- 4
- 5
示例 3:使用 overwrite=False
如果你不希望更新已经存在值的单元格,而只更新 NaN
值,可以将 overwrite=False
:
df1 = pd.DataFrame({
'A': [1, 2, 3, 4],
'B': [5, 6, 7, 8],
'C': [None, 10, None, 12]
})
df2 = pd.DataFrame({
'A': [10, 20],
'B': [50, 60],
'C': [15, 25]
}, index=[1, 2])
# 使用 update() 更新 df1,但不覆盖已存在的非 NaN 值
df1.update(df2, overwrite=False)
print(df1)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
输出:
A B C
0 1 5 NaN
1 20 50 15.0
2 20 60 25.0
3 4 8 12.0
- 1
- 2
- 3
- 4
- 5
说明:
- 由于
overwrite=False
,df1
中已有的NaN
值(例如A[0]
和C[0]
)被更新,而已存在的非NaN
值(例如C[3]
)没有被替换。
示例 4:update()
与 join='outer'
使用
df1 = pd.DataFrame({
'A': [1, 2],
'B': [3, 4]
}, index=[0, 1])
df2 = pd.DataFrame({
'A': [5, 6],
'C': [7, 8]
}, index=[1, 2])
# 使用 'outer' join,合并 df1 和 df2 的所有索引和列
df1.update(df2, join='outer')
print(df1)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
输出:
A B C
0 1.0 3.0 NaN
1 6.0 4.0 8.0
2 NaN NaN 7.0
- 1
- 2
- 3
- 4
说明:
- 使用
join='outer'
时,df1
中所有索引和列都会与df2
的索引和列合并。df2
中没有的值将填充为NaN
。
update()
的优缺点
优点:
update()
方法直接修改原始DataFrame
,它不会创建新的DataFrame
,因此可以节省内存。- 可以灵活地控制更新行为,通过
join
和overwrite
参数,可以适应不同的需求。
缺点:
update()
仅会替换原始DataFrame
中对应索引和列的部分。如果df2
中的某些行列不在df1
中,它们不会影响df1
。- 无法直接应用复杂的自定义操作(如根据条件更新),这时可能需要用其他方法(如
apply()
)来实现。
总结
- 添加新行:可以使用
append()
或concat()
方法。 - 更新已有行:可以通过
loc[]
或iloc[]
进行条件更新或按索引位置更新。 - 批量更新:使用
apply()
、where()
或其他条件逻辑进行批量更新。 - **update()**方法主要用于根据另一个
DataFrame
更新当前DataFrame
,并且具有灵活的参数来控制如何处理索引和更新规则。
固定窗口移动
rolling()
# Pandas `rolling` 方法总结
`rolling` 是 Pandas 中用于进行滑动窗口操作的函数,可以用于时间序列数据的聚合、平滑等操作。常见的聚合操作包括均值、和、标准差等,还可以与其他函数结合使用以实现更复杂的计算。
## 1. 基本用法
通过 `rolling(window)` 创建一个滑动窗口,`window` 表示窗口大小。
### 示例:
```
import pandas as pd
data = pd.Series([1, 2, 3, 4, 5, 6, 7, 8, 9])
# 计算每个窗口的均值
rolling_mean = data.rolling(window=3).mean()
print(rolling_mean)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
输出:
0 NaN
1 NaN
2 2.0
3 3.0
4 4.0
5 5.0
6 6.0
7 7.0
8 8.0
dtype: float64
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
常见的聚合操作
与 agg()
结合使用
agg()
允许在滑动窗口中使用多个聚合函数。
rolling_agg = data.rolling(window=3).agg(['sum', 'mean', 'std'])
- 1
与 apply()
结合使用
apply()
可以对每个窗口应用自定义的函数。
rolling_apply = data.rolling(window=3).apply(lambda x: x.max() - x.min())
- 1
与 shift()
结合使用
shift()
用于计算窗口之间的差异,通常用于滞后比较。
rolling_mean = data.rolling(window=3).mean()
rolling_diff = rolling_mean - rolling_mean.shift(1)
- 1
- 2
与 min()
和 max()
结合使用
min()
和 max()
计算窗口内的最小值和最大值。
rolling_min = data.rolling(window=3).min()
rolling_max = data.rolling(window=3).max()
- 1
- 2
与 corr()
和 cov()
结合使用
corr()
和 cov()
用于计算两个时间序列之间的相关性或协方差。
rolling_corr = data1.rolling(window=3).corr(data2)
- 1
与 cum*()
结合使用
cummin()
、cummax()
、cumsum()
等方法用于计算窗口的累计统计量。
rolling_cumsum = data.rolling(window=3).cumsum()
- 1
与 expanding()
结合使用
expanding()
创建一个从数据开始到当前位置的滑动窗口,用于计算累计值。
expanding_sum = data.expanding().sum()
- 1
常用参数
window
: 窗口大小,表示每个滑动窗口包含的数据量。min_periods
: 窗口内至少需要多少个有效数据才能进行计算,默认值为None
。center
: 默认为False
,表示窗口右对齐。如果设置为True
,窗口会以当前数据点为中心进行计算。
示例:
rolling_data = data.rolling(window=3, min_periods=2).mean()
- 1
总结
rolling
是 Pandas 中一个非常强大的工具,能够方便地对时间序列数据进行窗口聚合计算。与其他函数结合使用时,rolling
可以帮助我们实现更复杂的分析任务,适用于金融、工程、科学等多个领域的数据处理。
常用的组合方法包括:
agg()
: 多聚合函数应用。apply()
: 自定义计算。shift()
: 滞后操作。min()
,max()
: 窗口的最小值、最大值。corr()
,cov()
: 计算相关性和协方差。cum*()
: 累积统计。expanding()
: 扩展窗口的累计统计。
分组聚合
groupby()
基本用法
- 分组:通过指定一个或多个列名作为键来对数据进行分组。
- 聚合:对每个分组应用聚合函数,如求和(
sum()
)、平均值(mean()
)、最大值(max()
)、最小值(min()
)等。 - 重置索引:分组操作会改变DataFrame的索引,通常你会想要使用
reset_index()
方法来重置索引,使其成为一个普通的列。
示例
单键分组
import pandas as pd
# 创建一个简单的DataFrame
df = pd.DataFrame({
'Category': ['A', 'B', 'A', 'B', 'A'],
'Values': [10, 20, 30, 40, 50]
})
# 根据'Category'列进行分组,并计算每个组的和
grouped = df.groupby('Category')['Values'].sum().reset_index()
print(grouped)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
在这个例子中,数据被分为两组:‘A’ 和 ‘B’,然后计算了每个组的’Values’列的和。
多键分组
# 创建一个包含多个分类列的DataFrame
df_multi = pd.DataFrame({
'Category1': ['X', 'X', 'Y', 'Y'],
'Category2': ['A', 'B', 'A', 'B'],
'Values': [1, 2, 3, 4]
})
# 根据'Category1'和'Category2'列进行分组,并计算每个组的和
grouped_multi = df_multi.groupby(['Category1', 'Category2'])['Values'].sum().reset_index()
print(grouped_multi)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
在这个例子中,数据被分为四组:(‘X’, ‘A’)、(‘X’, ‘B’)、(‘Y’, ‘A’) 和 (‘Y’, ‘B’),然后计算了每个组的’Values’列的和。
应用多个聚合函数
# 使用agg方法应用多个聚合函数
grouped_agg = df.groupby('Category')['Values'].agg(['sum', 'mean', 'max', 'min']).reset_index()
print(grouped_agg)
- 1
- 2
- 3
- 4
在这个例子中,对每个分组应用了四个聚合函数:求和、平均值、最大值和最小值。
转换和过滤
除了聚合之外,groupby()
还可以与 transform()
方法结合使用来进行数据转换,或者与 filter()
方法结合使用来过滤数据。
# 使用transform方法计算每个组的平均值,并将其作为新列添加到原始DataFrame中
df['Mean'] = df.groupby('Category')['Values'].transform('mean')
print(df)
- 1
- 2
- 3
- 4
在这个例子中,每个组的’Values’列的平均值被计算出来,并作为新列’Mean’添加到了原始DataFrame中。
注意事项
- 当使用
groupby()
时,确保你理解分组键和聚合函数如何影响你的数据。 - 聚合操作会改变数据的形状,通常会导致某些行或列的丢失。
- 如果你的DataFrame很大,
groupby()
操作可能会比较耗时,特别是在多键分组或应用复杂聚合函数时。在这种情况下,考虑优化你的代码或使用更高效的数据处理策略。
transform
()
transform
用于对组内数据进行转换并返回与原始数据框形状相同的结果。它通常与groupby
一起使用,目的是对每个组进行操作后,将结果“广播”到原始数据框中。基本用法如下:
# 对每个组计算'value'列的均值,并将均值返回到原数据框中
df['mean_value'] = df.groupby('group')['value'].transform('mean')
print(df)
- 1
- 2
- 3
结合使用
在实际使用中,groupby
和transform
可以结合起来,从而对数据进行强大的分组计算。例如,计算每个分组的标准差并将其填充到原数据框中:
# 计算每个组的标准差,并将结果赋给原数据框
df['std_value'] = df.groupby('group')['value'].transform('std')
print(df)
- 1
- 2
- 3
apply()
基本用法
- 对列应用函数:默认情况下,
apply()
方法会对DataFrame的每一列应用函数。如果你想对行应用函数,需要设置axis=1
。 - 返回值:
apply()
方法返回一个新的Series(如果沿着列应用)或DataFrame(如果沿着行应用,且函数返回多个值)。 - 函数:你可以传递任何可调用对象(如函数、lambda表达式或方法)给
apply()
。
示例
对列应用函数
import pandas as pd
# 创建一个简单的DataFrame
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, 8, 9]
})
# 定义一个简单的函数,对每个元素加1
def add_one(x):
return x + 1
# 对每一列应用add_one函数
df_plus_one = df.apply(add_one)
print(df_plus_one)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
在这个例子中,add_one
函数被应用于DataFrame的每一列,每个元素都增加了1。
对行应用函数
# 定义一个函数,计算每行的和
def row_sum(row):
return row.sum()
# 对每一行应用row_sum函数
row_sums = df.apply(row_sum, axis=1)
print(row_sums)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
在这个例子中,row_sum
函数被应用于DataFrame的每一行,计算每行的和,并返回一个Series。
使用lambda函数
# 使用lambda函数对每一列的元素乘以2
df_multiplied = df.apply(lambda x: x * 2)
print(df_multiplied)
- 1
- 2
- 3
- 4
在这个例子中,一个lambda函数被用于将DataFrame中每个元素乘以2。
处理复杂的数据结构
如果你的DataFrame包含复杂的数据结构(如列表或字典),你可以编写更复杂的函数来处理这些数据。
# 创建一个包含列表的DataFrame
df_complex = pd.DataFrame({
'data': [[1, 2], [3, 4], [5, 6]]
})
# 定义一个函数,计算列表中元素的和
def sum_list(lst):
return sum(lst)
# 对'data'列应用sum_list函数
sums = df_complex['data'].apply(sum_list)
print(sums)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
在这个例子中,sum_list
函数被用于计算DataFrame中’data’列每个列表元素的和。
注意事项
- 当对大型DataFrame使用
apply()
时,性能可能会受到影响,因为Pandas需要将数据逐行或逐列传递给Python函数。在可能的情况下,优先考虑使用Pandas的内置向量化操作来提高性能。 - 如果你的函数返回多个值,并且你希望对行应用该函数,确保你的函数返回一个Series或类似的结构,这样Pandas才能正确地将其组装成一个新的DataFrame。
map()
在 pandas 中,map
函数是一种用于将一个函数或映射关系应用到 DataFrame 或 Series 的每个元素上的方法。对于 Series 对象,map
方法特别有用,因为它允许你将一个函数、字典或 Series 应用到 Series 的每个元素上,并返回一个新的 Series,其中包含应用映射后的结果。
以下是 map
方法的一些常见用法:
在 Series 中
import pandas as pd
# 创建一个 Series
s = pd.Series([1, 2, 3, 4, 5])
# 定义一个函数
def square(x):
return x ** 2
# 使用 map 方法应用函数
squared_s = s.map(square)
print(squared_s)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
在这个例子中,square
函数被应用到 s
Series 的每个元素上,结果是一个包含每个元素平方的新 Series。
字典进行映射
# 创建一个 Series
s = pd.Series(['cat', 'dog', 'fish', 'cat'])
# 定义一个映射字典
animal_to_sound = {'cat': 'meow', 'dog': 'woof', 'fish': 'glub'}
# 使用 map 方法应用字典映射
sounded_s = s.map(animal_to_sound)
print(sounded_s)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
在这个例子中,animal_to_sound
字典被用来将动物名称映射到它们的声音,结果是一个包含映射后声音的新 Series。
另一个 Series 进行映射
# 创建两个 Series
s1 = pd.Series(['a', 'b', 'c', 'd'])
s2 = pd.Series(['apple', 'banana', 'cherry', 'date'], index=['a', 'b', 'c', 'd'])
# 使用 map 方法应用 Series 映射
mapped_s = s1.map(s2)
print(mapped_s)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
在这个例子中,s2
Series 被用作映射,将 s1
中的每个元素映射到 s2
中对应索引的值。注意,如果 s1
中的某个元素在 s2
的索引中找不到,结果将是 NaN
。
对于 DataFrame,map
方法通常不是直接应用的,因为 DataFrame 是二维的,包含行和列。相反,你可能会对 DataFrame 的某一列使用 map
方法,或者对整个 DataFrame 使用 applymap
方法(但请注意,applymap
是应用于每个元素的,与 map
在 Series 上的行为类似,但它不接受函数以外的映射器)。
这里有一个对 DataFrame 列使用 map
的例子:
# 创建一个 DataFrame
df = pd.DataFrame({
'Animal': ['cat', 'dog', 'fish', 'cat'],
'Age': [2, 3, 1, 4]
})
# 使用 map 方法对 'Animal' 列应用字典映射
df['Sound'] = df['Animal'].map(animal_to_sound)
print(df)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
在这个例子中,animal_to_sound
字典被用来将 df
DataFrame 中 'Animal'
列的每个元素映射到它们的声音,结果是一个新的列 'Sound'
。
索引操作
idxmax()
总结:
DataFrame.idxmax():返回每列的最大值的行索引
Series.idxmax():返回单列的最大值的行索引
在 Pandas 中,idxmax()
函数用于返回指定轴上最大值的索引。这个函数对于寻找数据集中某个特定列(或行,取决于你如何应用它)的最大值的位置非常有用。
基本用法
假设你有一个 Pandas DataFrame 或 Series,idxmax()
会返回包含最大值的行(对于 DataFrame,默认是列方向)或元素(对于 Series)的索引。
import pandas as pd
# 创建一个简单的 DataFrame
df = pd.DataFrame({
'A': [1, 20, 3, 4],
'B': [5, 6, 70, 8]
})
# 对列 'A' 使用 idxmax()
max_index_A = df['A'].idxmax()
print(f"Column 'A' maximum value index: {max_index_A}")
# 对整个 DataFrame 使用 idxmax(),默认是 axis=0(列方向)
max_index_df = df.idxmax()
print(f"DataFrame maximum value indices (column-wise): {max_index_df}")
# 对 DataFrame 使用 idxmax(),指定 axis=1(行方向)
max_index_df_row = df.idxmax(axis=1)
print(f"DataFrame maximum value indices (row-wise): {max_index_df_row}")
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
输出
Column 'A' maximum value index: 1
DataFrame maximum value indices (column-wise): A 1
B 2
dtype: int64
DataFrame maximum value indices (row-wise): 0 B
1 A
2 B
3 B
dtype: object
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
解释
-
对于
df['A'].idxmax()
,它返回列 ‘A’ 中最大值(20)的索引(1)。 -
对于
df.idxmax()
(默认axis=0
),它返回每一列中最大值的索引。在这个例子中,列 ‘A’ 的最大值在索引 1,列 ‘B’ 的最大值在索引 2。 -
对于
df.idxmax(axis=1)
,它返回每一行中最大值的列索引。在这个例子中,第一行的最大值在列 ‘B’,第二行的最大值在列 ‘A’,依此类推。
注意事项
- 如果存在多个最大值并且你想要找到它们所有的索引,
idxmax()
只会返回第一个找到的最大值的索引。 - 如果 DataFrame 或 Series 是空的,
idxmax()
会抛出一个ValueError
。 - 如果 DataFrame 中包含
NaN
值,并且你想要在忽略NaN
的情况下找到最大值,你应该先使用dropna()
方法去除NaN
值,然后再应用idxmax()
。
reset_index()
在Pandas中,reset_index()
方法用于重置 DataFrame 或 Series 的索引。这个操作通常在你对数据进行了排序、分组、过滤等操作后,索引变得不再连续或不再是整数时特别有用。通过重置索引,可以使索引重新变为从 0 开始的整数序列,或者可以将某个列的值设置为新的索引。
以下是 reset_index()
方法的一些常用参数及其作用:
drop
(布尔值,默认为 False):如果为 True,则不将旧索引添加为列;如果为 False,则旧索引会被添加为新的 DataFrame 的一列。inplace
(布尔值,默认为 False):如果为 True,则直接在原 DataFrame 上修改,不返回新的 DataFrame。level
(整数或索引级别名称,或级别列表):仅对多级索引有效。指定要重置的索引级别。col_level
(整数或索引级别名称):如果 DataFrame 的列是多级索引,则此参数指定用于新索引的列级别。col_fill
(字符串):用于填充多级列索引中缺失级别的值。
示例
参数name
例如,假设有一个DataFrame,其中’Name’列被设置为索引。如果想要重置这个索引,并且希望新的索引列有一个特定的名称(比如’ID’),就可以这样做:
df.set_index('Name', inplace=True) # 将'Name'列设置为索引
reset_df = df.reset_index(name='ID') # 重置索引,并指定新索引列的名称为'ID'
- 1
- 2
执行上述代码后,原来的’Name’索引就会被重置,并且会添加一个新的名为’ID’的列,其中包含了原来的索引值。
无参数
假设我们有一个 DataFrame:
import pandas as pd
df = pd.DataFrame({
'A': ['foo', 'bar', 'baz', 'qux'],
'B': [1, 2, 3, 4]
})
df = df.set_index('A')
print(df)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
输出:
B
A
foo 1
bar 2
baz 3
qux 4
- 1
- 2
- 3
- 4
- 5
- 6
现在我们将索引重置:
df_reset = df.reset_index()
print(df_reset)
- 1
- 2
输出:
A B
0 foo 1
1 bar 2
2 baz 3
3 qux 4
- 1
- 2
- 3
- 4
- 5
可以看到,原来的索引 ‘A’ 现在成为了一列,并且添加了一个新的从 0 开始的整数索引。
参数drop
如果我们不想保留原来的索引作为列,可以设置 drop=True
:
df_reset = df.reset_index(drop=True)
print(df_reset)
- 1
- 2
输出:
B
0 1
1 2
2 3
3 4
- 1
- 2
- 3
- 4
- 5
此时,原来的索引 ‘A’ 被丢弃,只保留了数据列 ‘B’ 和一个新的整数索引。
多级索引
对于多级索引,可以使用 level
参数来指定要重置的级别:
# 创建一个多级索引的 DataFrame
multi_index = pd.MultiIndex.from_tuples([('foo', 'one'), ('foo', 'two'), ('bar', 'one'), ('bar', 'two')], names=['A', 'B'])
df_multi = pd.DataFrame({'C': [1, 2, 3, 4]}, index=multi_index)
print(df_multi)
# 重置 'A' 级别的索引
df_reset_multi = df_multi.reset_index(level='A')
print(df_reset_multi)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
T
转置:列, 行交换
元素定位
at
- 用于访问单个值(标量访问),基于标签(label)进行索引。
- 只能用于访问单个元素,如果访问多个元素会引发错误。
- 适用于快速访问已知标签的数据。
df.at[row_label, column_label]
- 1
- 2
iat
- 类似于
at
,但基于整数位置进行标量访问。 - 适用于快速访问已知位置的单个元素。
df.iat[row_position, column_position]
- 1
loc
- 基于标签(label)进行索引,可以用于访问单个值或一组值。
- 支持切片操作,可以访问行或列的子集。
- 适用于基于标签的复杂查询。
df.loc[row_labels, column_labels]
- 1
- 2
iloc
- 基于整数位置(integer position)进行索引,用于访问单个值或一组值。
- 支持切片操作,可以访问行或列的子集。
- 适用于基于位置的索引,当标签不是整数或不方便使用标签时很有用。
df.iloc[row_positions, column_positions]
- 1
- 2
两个序列操作
isin()
在 Pandas 中,isin()
方法用于过滤数据框(DataFrame)或序列(Series)中的元素,检查它们是否包含在指定的值列表或序列中。该方法返回一个布尔型对象(对于 DataFrame,返回一个布尔型的 DataFrame;对于 Series,返回一个布尔型的 Series),其中 True
表示元素包含在指定的值中,False
表示不包含。
以下是 isin()
方法的基本用法:
对于 Series
import pandas as pd
# 创建一个 Series
s = pd.Series([1, 2, 3, 4, 5])
# 使用 isin() 方法检查 Series 中的元素是否包含在 [1, 3, 5] 中
filtered_s = s[s.isin([1, 3, 5])]
print(filtered_s)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
输出将会是:
0 1
2 3
4 5
dtype: int64
- 1
- 2
- 3
- 4
对于 DataFrame
import pandas as pd
# 创建一个 DataFrame
df = pd.DataFrame({
'A': [1, 2, 3, 4, 5],
'B': [10, 20, 30, 40, 50]
})
# 使用 isin() 方法检查 DataFrame 的列 'A' 中的元素是否包含在 [1, 3, 5] 中
filtered_df = df[df['A'].isin([1, 3, 5])]
print(filtered_df)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
输出将会是:
A B
0 1 10
2 3 30
4 5 50
- 1
- 2
- 3
- 4
你也可以对 DataFrame 的多列使用 isin()
方法,但这时你需要分别对每个列进行过滤,或者结合使用其他逻辑操作(如 &
、|
)来组合多个过滤条件。
对多列使用 isin()(结合逻辑操作)
# 假设我们想要过滤出列 'A' 中的元素在 [1, 3] 中且列 'B' 中的元素在 [10, 30, 50] 中的行
combined_filter = (df['A'].isin([1, 3]) & df['B'].isin([10, 30, 50]))
filtered_df_multi = df[combined_filter]
print(filtered_df_multi)
- 1
- 2
- 3
- 4
- 5
输出将会是:
A B
0 1 10
2 3 30
4 5 50 # 注意:虽然 5 在 [1, 3] 中不在,但 50 在 [10, 30, 50] 中,所以这一行不会单独因为 B 列而被选中
# 但由于 5 不在 [1, 3] 中,所以实际上这一行不会被包括在结果中,这里只是为了解释逻辑操作。
# 正确的输出不会包含索引为 4 的行,因为它不满足 A 列的条件。
- 1
- 2
- 3
- 4
- 5
- 6
注意:上面的多列过滤示例中,我犯了一个错误并给出了一个误导性的输出解释。正确的行为是,只有当行同时满足所有列的条件时,它才会被包括在结果中。因此,在上面的例子中,索引为 4 的行不会被包括,因为 A
列的值 5
不在 [1, 3]
中。正确的输出应该只包含索引为 0 和 2 的行
评论记录:
回复评论: