49_Pandas.DataFrame添加列和行(分配、追加等)
如何向 pandas.DataFrame 添加新的列或行。
通过指定新的列名/行名来添加,或者用pandas.DataFrame的assign()、insert()、append()方法添加等方法。
这里,将描述以下内容。
- 将列添加到 pandas.DataFrame
- 通过指定新列名添加
- 用assign()方法添加/分配
- 用insert()方法添加到任意位置
- 使用 concat() 函数水平连接 Series 和 DataFrame
- 向pandas.DataFrame 添加一行
- 通过指定新行名称添加
- 用append()方法添加
- 使用 concat() 函数垂直连接 Series 和 DataFrame
- 转置然后使用assign()、insert()方法
简要介绍连接 pandas.DataFrame 和 pandas.Series 的 pandas.concat() 函数,但有关详细信息,请参阅以下文章。
例如,创建并使用以下对象。
import pandas as pd
df = pd.DataFrame({
'A': ['A1', 'A2', 'A3'],
'B': ['B1', 'B2', 'B3'],
'C': ['C1', 'C2', 'C3']},
index=['ONE', 'TWO', 'THREE'])
print(df)
# A B C
# ONE A1 B1 C1
# TWO A2 B2 C2
# THREE A3 B3 C3
将列添加到 pandas.DataFrame
通过指定新列名添加
可以在[列名]中选择一列并赋值。
df['A'] = 0
print(df)
# A B C
# ONE 0 B1 C1
# TWO 0 B2 C2
# THREE 0 B3 C3
通过指定此处尚不存在的列名称,可以添加该列并分配值。 添加标量 对于标量值,所有元素都是它们的值。
df['D'] = 0
print(df)
# A B C D
# ONE 0 B1 C1 0
# TWO 0 B2 C2 0
# THREE 0 B3 C3 0b
添加类似数组的对象 在所谓的类数组对象(例如列表和 NumPy 数组 ndarray)的情况下,每个元素都按原样分配。
df['E'] = [0, 1, 2]
print(df)
# A B C D E
# ONE 0 B1 C1 0 0
# TWO 0 B2 C2 0 1
# THREE 0 B3 C3 0 2
如果要添加的列表等元素数量与行数不匹配,则会发生错误(ValueError)。
# df['F'] = [0, 1, 2, 3]
# ValueError: Length of values does not match length of index
添加了 pandas.Series 也可以使用 pandas.Series。 如果引用pandas.DataFrame的每一列,都会被当作pandas.Series处理,所以可以将这些操作的结果和方法处理的结果作为一个新的列进行添加。
df['F'] = df['B'] + df['C']
df['G'] = df['B'].str.lower()
print(df)
# A B C D E F G
# ONE 0 B1 C1 0 0 B1C1 b1
# TWO 0 B2 C2 0 1 B2C2 b2
# THREE 0 B3 C3 0 2 B3C3 b3
如果pandas.Series的标签索引与pandas.DataFrame的列名索引不匹配,则赋值为缺失值NaN。
s = pd.Series(['X2', 'X3', 'X4'], index=['TWO', 'THREE', 'FOUR'], name='X')
print(s)
# TWO X2
# THREE X3
# FOUR X4
# Name: X, dtype: object
df['H'] = s
print(df)
# A B C D E F G H
# ONE 0 B1 C1 0 0 B1C1 b1 NaN
# TWO 0 B2 C2 0 1 B2C2 b2 X2
# THREE 0 B3 C3 0 2 B3C3 b3 X3
如果你拿到带有pandas.Series的values属性的NumPy数组numpy.ndarray并赋值,不管索引如何,元素都会按顺序赋值。在这种情况下,如果元素数与行数不匹配,则会发生错误。
print(s.values)
# ['X2' 'X3' 'X4']
df['I'] = s.values
print(df)
# A B C D E F G H I
# ONE 0 B1 C1 0 0 B1C1 b1 NaN X2
# TWO 0 B2 C2 0 1 B2C2 b2 X2 X3
# THREE 0 B3 C3 0 2 B3C3 b3 X3 X4
用assign()方法添加/分配
Assign() 是作为向pandas.DataFrame 添加新列或为现有列分配新值的方法提供的。
在assign()方法中,用关键字参数column name = value指定列名及其值。 如果是现有列名,则赋值,如果是新列名,则添加新列。
df = pd.DataFrame({
'A': ['A1', 'A2', 'A3'],
'B': ['B1', 'B2', 'B3'],
'C': ['C1', 'C2', 'C3']},
index=['ONE', 'TWO', 'THREE'])
print(df.assign(A=0))
# A B C
# ONE 0 B1 C1
# TWO 0 B2 C2
# THREE 0 B3 C3
print(df.assign(D=0))
# A B C D
# ONE A1 B1 C1 0
# TWO A2 B2 C2 0
# THREE A3 B3 C3 0
返回一个新对象,原始对象不变。
print(df)
# A B C
# ONE A1 B1 C1
# TWO A2 B2 C2
# THREE A3 B3 C3
还可以指定列表、pandas.Series 等,如在上面的 [Column name] 中添加的示例中所示。还可以指定多个关键字参数并一次添加/分配多个列。
s = pd.Series(['X2', 'X3', 'X4'], index=['TWO', 'THREE', 'FOUR'], name='X')
print(s)
# TWO X2
# THREE X3
# FOUR X4
# Name: X, dtype: object
df_new = df.assign(C='XXX',
D=0, E=[0, 1, 2],
F=s, G=s.values,
H=df['A'] + df['B'])
print(df_new)
# A B C D E F G H
# ONE A1 B1 XXX 0 0 NaN X2 A1B1
# TWO A2 B2 XXX 0 1 X2 X3 A2B2
# THREE A3 B3 XXX 0 2 X3 X4 A3B3
用insert()方法添加到任意位置
[列名] 规范和assign() 方法在原pandas.DataFrame 的末尾(右侧)添加一个新列,但是insert() 方法可用于在任何位置添加列。
在第一个参数中指定位置,在第二个参数中指定列名,在第三个参数中指定要添加的值。 标量值和列表等类数组对象,以及pandas.Series可以指定为第三个参数。这个想法与前面的例子相同。 原始 DataFrame 本身已更新。
df = pd.DataFrame({
'A': ['A1', 'A2', 'A3'],
'B': ['B1', 'B2', 'B3'],
'C': ['C1', 'C2', 'C3']},
index=['ONE', 'TWO', 'THREE'])
s = pd.Series(['X2', 'X3', 'X4'], index=['TWO', 'THREE', 'FOUR'], name='X')
df.insert(0, 'D', 0)
print(df)
# D A B C
# ONE 0 A1 B1 C1
# TWO 0 A2 B2 C2
# THREE 0 A3 B3 C3
df.insert(len(df.columns), 'E', s)
print(df)
# D A B C E
# ONE 0 A1 B1 C1 NaN
# TWO 0 A2 B2 C2 X2
# THREE 0 A3 B3 C3 X3
如果指定的值超过第一个参数中的行数,则会出错。也不能用负值从后面指定位置。最后,使用 len (df.columns) 或 df.shape [1] 获取行数并指定它。
# df.insert(10, 'F', 10)
# ValueError: cannot insert F, already exists
# df.insert(-1, 'F', 10)
# ValueError: unbounded slice
如果您指定的列名已存在于第二个参数中,则会出错。如果参数 allow_duplicates 设置为 True 可以添加它,但不推荐这样做,因为列名会重复。
# df.insert(0, 'D', 10)
# ValueError: cannot insert D, already exists
df.insert(0, 'D', 10, allow_duplicates=True)
print(df)
# D D A B C E
# ONE 10 0 A1 B1 C1 NaN
# TWO 10 0 A2 B2 C2 X2
# THREE 10 0 A3 B3 C3 X3
使用 concat() 函数水平连接 Series 和 DataFrame
在前面的例子中,当添加 pandas.Series 时,它的 name 属性被忽略了。 当在pandas.concat()函数中与参数axis = 1水平连接时,pandas.Series的名称成为pandas.DataFrame的列名。 在pandas.concat()的第一个参数中指定其元素是要连接的对象的列表或元组。
df = pd.DataFrame({
'A': ['A1', 'A2', 'A3'],
'B': ['B1', 'B2', 'B3'],
'C': ['C1', 'C2', 'C3']},
index=['ONE', 'TWO', 'THREE'])
s = pd.Series(['X2', 'X3', 'X4'], index=['TWO', 'THREE', 'FOUR'], name='X')
print(pd.concat([df, s], axis=1))
# A B C X
# ONE A1 B1 C1 NaN
# TWO A2 B2 C2 X2
# THREE A3 B3 C3 X3
# FOUR NaN NaN NaN X4
也可以只留下具有公共行名称的行作为参数 join =‘inner’。
print(pd.concat([df, s], axis=1, join='inner'))
# A B C X
# TWO A2 B2 C2 X2
# THREE A3 B3 C3 X3
还可以连接多个 pandas.Series 和连接 pandas.DataFrame。
s1 = pd.Series(['X1', 'X2', 'X3'], index=df.index, name='X')
s2 = pd.Series(['Y1', 'Y2', 'Y3'], index=df.index, name='Y')
print(pd.concat([df, s1, s2], axis=1))
# A B C X Y
# ONE A1 B1 C1 X1 Y1
# TWO A2 B2 C2 X2 Y2
# THREE A3 B3 C3 X3 Y3
df2 = pd.DataFrame({
'df_col1': 0, 'df_col2': range(3)}, index=df.index)
print(df2)
# df_col1 df_col2
# ONE 0 0
# TWO 0 1
# THREE 0 2
print(pd.concat([df, df2], axis=1))
# A B C df_col1 df_col2
# ONE A1 B1 C1 0 0
# TWO A2 B2 C2 0 1
# THREE A3 B3 C3 0 2
有关 pandas.concat() 函数的更多信息,请参阅以下文章。
* 02_Pandas.concat连接DataFrame,Series
*
向pandas.DataFrame 添加一行
通过指定新行名称添加
可以使用 iloc [row name] 选择一行并分配一个值。
df = pd.DataFrame({
'A': ['A1', 'A2', 'A3'],
'B': ['B1', 'B2', 'B3'],
'C': ['C1', 'C2', 'C3']},
index=['ONE', 'TWO', 'THREE'])
print(df)
# A B C
# ONE A1 B1 C1
# TWO A2 B2 C2
# THREE A3 B3 C3
df.loc['ONE'] = 0
print(df)
# A B C
# ONE 0 0 0
# TWO A2 B2 C2
# THREE A3 B3 C3
与列一样,可以添加该行并通过指定此处不存在的行名称来分配值。 这个想法与列相同。可以添加类似数组的对象,例如标量值和列表。
df.loc['FOUR'] = 0
df.loc['FIVE'] = ['A5', 'B5', 'C5']
print(df)
# A B C
# ONE 0 0 0
# TWO A2 B2 C2
# THREE A3 B3 C3
# FOUR 0 0 0
# FIVE A5 B5 C5
在类数组对象的情况下,如果元素数和列数不匹配,则会发生错误(ValueError)。
# df.loc['SIX'] = ['A6', 'B6']
# ValueError: cannot set a row with mismatched columns
Pandas.Series 与列相同。如果标签不匹配,则分配缺失值 NaN。如果要忽略标签,请在值中使用 numpy.ndarray。
s = pd.Series(['B6', 'C6', 'D6'], index=['B', 'C', 'D'], name='SIX')
print(s)
# B B6
# C C6
# D D6
# Name: SIX, dtype: object
df.loc['XXX'] = df.loc['TWO'] + df.loc['THREE']
df.loc['YYY'] = s
df.loc['ZZZ'] = s.values
print(df)
# A B C
# ONE 0 0 0
# TWO A2 B2 C2
# THREE A3 B3 C3
# FOUR 0 0 0
# FIVE A5 B5 C5
# XXX A2A3 B2B3 C2C3
# YYY NaN B6 C6
# ZZZ B6 C6 D6
用append()方法添加
提供了一个 append() 方法来向 pandas.DataFrame 添加新行。
指定要添加到第一个参数的对象。 基本上,pandas.Series 和pandas.DataFrame 以及将它们作为元素的列表和元组可以指定为第一个参数。 指定标量值或列表可能会导致错误或意外结果。可以在字典中指定它,但不会很实用。
df = pd.DataFrame({
'A': ['A1', 'A2', 'A3'],
'B': ['B1', 'B2', 'B3'],
'C': ['C1', 'C2', 'C3']},
index=['ONE', 'TWO', 'THREE'])
# print(df.append(0))
# TypeError: cannot concatenate object of type '<class 'int'>'; only Series and DataFrame objs are valid
print(df.append([0, 1, 2]))
# A B C 0
# ONE A1 B1 C1 NaN
# TWO A2 B2 C2 NaN
# THREE A3 B3 C3 NaN
# 0 NaN NaN NaN 0.0
# 1 NaN NaN NaN 1.0
# 2 NaN NaN NaN 2.0
print(df.append({
'A': 0, 'B': 1, 'C': 2}, ignore_index=True))
# A B C
# 0 A1 B1 C1
# 1 A2 B2 C2
# 2 A3 B3 C3
# 3 0 1 2
当第一个参数指定pandas.Series时,原始pandas.DataFrame的列名列和pandas.Series的标签索引对应。如果它们不匹配,则替换缺失值 NaN。 pandas.Series 的 name 属性成为新的行名称。
s = pd.Series(['A4', 'B4', 'C4'], index=df.columns, name='FOUR')
print(df.append(s))
# A B C
# ONE A1 B1 C1
# TWO A2 B2 C2
# THREE A3 B3 C3
# FOUR A4 B4 C4
s_mismatch = pd.Series(['B5', 'C5', 'D5'], index=['B', 'C', 'D'], name='FIVE')
print(df.append(s_mismatch))
# A B C D
# ONE A1 B1 C1 NaN
# TWO A2 B2 C2 NaN
# THREE A3 B3 C3 NaN
# FIVE NaN B5 C5 D5
返回一个新对象,原对象不变.
print(df)
# A B C
# ONE A1 B1 C1
# TWO A2 B2 C2
# THREE A3 B3 C3
如果名称属性未在 pandas.Series 中设置,则会出错。可以通过将参数 ignore_index 设置为 True 来添加它,但所有行名称索引都将被忽略,并且序列号以 0 开头。
s_no_name = pd.Series(['B4', 'C4', 'D4'], index=['B', 'C', 'D'])
# print(df.append(s_no_name))
# TypeError: Can only append a Series if ignore_index=True or if the Series has a name
print(df.append(s_no_name, ignore_index=True))
# A B C D
# 0 A1 B1 C1 NaN
# 1 A2 B2 C2 NaN
# 2 A3 B3 C3 NaN
# 3 NaN B4 C4 D4
可以通过将列表或元组指定为第一个参数来添加多个对象。
print(df.append([s, s_mismatch]))
# A B C D
# ONE A1 B1 C1 NaN
# TWO A2 B2 C2 NaN
# THREE A3 B3 C3 NaN
# FOUR A4 B4 C4 NaN
# FIVE NaN B5 C5 D5
还可以指定 pandas.DataFrame。
df2 = pd.DataFrame([['B6', 'C6', 'D6'], ['B7', 'C7', 'D7']],
index=['SIX', 'SEVEN'], columns=['B', 'C', 'D'])
print(df2)
# B C D
# SIX B6 C6 D6
# SEVEN B7 C7 D7
print(df.append(df2))
# A B C D
# ONE A1 B1 C1 NaN
# TWO A2 B2 C2 NaN
# THREE A3 B3 C3 NaN
# SIX NaN B6 C6 D6
# SEVEN NaN B7 C7 D7
包含 pandas.DataFrame 和 pandas.Series 的列表是错误的。重复调用append()是可以的。
# print(df.append([s, df2]))
# ValueError: all the input array dimensions for the concatenation axis must match exactly, but along dimension 1, the array at index 0 has size 5 and the array at index 1 has size 3
print(df.append(s).append(df2))
# A B C D
# ONE A1 B1 C1 NaN
# TWO A2 B2 C2 NaN
# THREE A3 B3 C3 NaN
# FOUR A4 B4 C4 NaN
# SIX NaN B6 C6 D6
# SEVEN NaN B7 C7 D7
使用 concat() 函数垂直连接 Series 和 DataFrame
还可以将 pandas.DataFrames 与 pandas.concat () 函数连接起来。 在pandas.concat()的第一个参数中指定其元素是要连接的对象的列表或元组。默认情况下,它们是垂直连接的。
print(pd.concat([df, df2]))
# A B C D
# ONE A1 B1 C1 NaN
# TWO A2 B2 C2 NaN
# THREE A3 B3 C3 NaN
# SIX NaN B6 C6 D6
# SEVEN NaN B7 C7 D7
也可以只留下具有公共列名的列作为参数 join =‘inner’。
print(pd.concat([df, df2], join='inner'))
# B C
# ONE B1 C1
# TWO B2 C2
# THREE B3 C3
# SIX B6 C6
# SEVEN B7 C7
垂直连接 pandas.DataFrame 和 pandas.Series 时要小心。 如果使用append()方法,会添加如下。
print(df.append(s))
# A B C
# ONE A1 B1 C1
# TWO A2 B2 C2
# THREE A3 B3 C3
# FOUR A4 B4 C4
另一方面,在 pandas.concat() 函数的情况下,它将如下所示。
print(pd.concat([df, s]))
# A B C 0
# ONE A1 B1 C1 NaN
# TWO A2 B2 C2 NaN
# THREE A3 B3 C3 NaN
# A NaN NaN NaN A4
# B NaN NaN NaN B4
# C NaN NaN NaN C4
如果从pandas.Series 生成pandas.DataFrame 并进一步转置,则可以使用pandas.concat() 进行连接,但使用append() 方法会更直接。
print(pd.DataFrame(s).T)
# A B C
# FOUR A4 B4 C4
print(pd.concat([df, pd.DataFrame(s).T]))
# A B C
# ONE A1 B1 C1
# TWO A2 B2 C2
# THREE A3 B3 C3
# FOUR A4 B4 C4
转置然后使用assign()、insert()方法
如果要使用assign()方法添加一行,也可以转置pandas.DataFrame,使用assign()方法,再转回原样。这可能不是一个很好的方法。
print(df.T.assign(FOUR=0, FIVE=['A5', 'B5', 'C5']).T)
# A B C
# ONE A1 B1 C1
# TWO A2 B2 C2
# THREE A3 B3 C3
# FOUR 0 0 0
# FIVE A5 B5 C5
也可以使用insert()方法,但是insert()更新的是原来的pandas.DataFrame本身,不能写在方法链中。
# df_insert = df.T.insert(0, 'FOUR', 0).T
# AttributeError: 'NoneType' object has no attribute 'T'
df_T = df.T
df_T.insert(0, 'FOUR', 0)
print(df_T.T)
# A B C
# FOUR 0 0 0
# ONE A1 B1 C1
# TWO A2 B2 C2
# THREE A3 B3 C3