49_Pandas.DataFrame添加列和行(分配、追加等)

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

猜你喜欢

转载自blog.csdn.net/qq_18351157/article/details/122337643
今日推荐