关于python:将一行添加到pandas 数据帧

Add one row to pandas DataFrame

我知道Pandas是为加载完全填充的DataFrame而设计的,但是我需要创建一个空数据帧,然后逐个添加行。最好的方法是什么?

我成功地创建了一个空数据帧,其中包含:

1
res = DataFrame(columns=('lib', 'qty1', 'qty2'))

然后我可以添加新行并用以下内容填充字段:

1
res = res.set_value(len(res), 'qty1', 10.0)

它可以工作,但看起来很奇怪:-/(它不能添加字符串值)

如何将新行添加到我的数据框架(具有不同的列类型)?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> import pandas as pd
>>> from numpy.random import randint

>>> df = pd.DataFrame(columns=['lib', 'qty1', 'qty2'])
>>> for i in range(5):
>>>     df.loc[i] = ['name' + str(i)] + list(randint(10, size=2))

>>> df
     lib qty1 qty2
0  name0    3    3
1  name1    2    4
2  name2    2    8
3  name3    2    1
4  name4    9    6


如果您可以预先获得数据帧的所有数据,那么有一种比附加到数据帧更快的方法:

  • 创建一个字典列表,其中每个字典对应一个输入数据行。
  • 从此列表创建数据帧。
  • 我有一个类似的任务,一行一行地附加到一个数据帧需要30分钟,然后从几秒钟内完成的字典列表中创建一个数据帧。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    rows_list = []
    for row in input_rows:

            dict1 = {}
            # get input row in dictionary format
            # key = col_name
            dict1.update(blah..)

            rows_list.append(dict1)

    df = pd.DataFrame(rows_list)


    您可以使用pandas.concat()DataFrame.append()。有关详细信息和示例,请参见合并、联接和连接。


    如果您事先知道条目数,则还应通过提供索引(以不同答案的数据为例)来预先分配空间:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import pandas as pd
    import numpy as np
    # we know we're gonna have 5 rows of data
    numberOfRows = 5
    # create dataframe
    df = pd.DataFrame(index=np.arange(0, numberOfRows), columns=('lib', 'qty1', 'qty2') )

    # now fill it up row by row
    for x in np.arange(0, numberOfRows):
        #loc or iloc both work here since the index is natural numbers
        df.loc[x] = [np.random.randint(-1,1) for n in range(3)]
    In[23]: df
    Out[23]:
       lib  qty1  qty2
    0   -1    -1    -1
    1    0     0     0
    2   -1     0    -1
    3    0    -1     0
    4   -1     0     0

    速度比较

    1
    2
    3
    4
    In[30]: %timeit tryThis() # function wrapper for this answer
    In[31]: %timeit tryOther() # function wrapper without index (see, for example, @fred)
    1000 loops, best of 3: 1.23 ms per loop
    100 loops, best of 3: 2.31 ms per loop

    从评论中可以看出,6000码的速度差更大:

    Increasing the size of the array (12) and the number of rows (500) makes
    the speed difference more striking: 313ms vs 2.29s


    要获得有效的附加,请参阅如何向熊猫数据帧中添加额外的行,并使用放大设置。

    通过loc/ix在不存在的键索引数据上添加行。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    In [1]: se = pd.Series([1,2,3])

    In [2]: se
    Out[2]:
    0    1
    1    2
    2    3
    dtype: int64

    In [3]: se[5] = 5.

    In [4]: se
    Out[4]:
    0    1.0
    1    2.0
    2    3.0
    5    5.0
    dtype: float64

    或:

    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
    In [1]: dfi = pd.DataFrame(np.arange(6).reshape(3,2),
       .....:                 columns=['A','B'])
       .....:

    In [2]: dfi
    Out[2]:
       A  B
    0  0  1
    1  2  3
    2  4  5

    In [3]: dfi.loc[:,'C'] = dfi.loc[:,'A']

    In [4]: dfi
    Out[4]:
       A  B  C
    0  0  1  0
    1  2  3  2
    2  4  5  4
    In [5]: dfi.loc[3] = 5

    In [6]: dfi
    Out[6]:
       A  B  C
    0  0  1  0
    1  2  3  2
    2  4  5  4
    3  5  5  5


    1
    2
    3
    4
    5
    mycolumns = ['A', 'B']
    df = pd.DataFrame(columns=mycolumns)
    rows = [[1,2],[3,4],[5,6]]
    for row in rows:
        df.loc[len(df)] = row


    您可以使用ignore_index选项附加一行作为字典。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> f = pandas.DataFrame(data = {'Animal':['cow','horse'], 'Color':['blue', 'red']})
    >>> f
      Animal Color
    0    cow  blue
    1  horse   red
    >>> f.append({'Animal':'mouse', 'Color':'black'}, ignore_index=True)
      Animal  Color
    0    cow   blue
    1  horse    red
    2  mouse  black


    已经很久了,但我也面临同样的问题。在这里找到了很多有趣的答案。所以我很困惑该用什么方法。

    在向数据帧添加大量行的情况下,我对速度性能感兴趣。所以我尝试了三种最流行的方法并检查了它们的速度。

    2019年使用新版本的软件包更新

    速度性能

  • 使用.append(NPE的答案)
  • 使用.loc(fred的答案和foobar的答案)
  • 使用dict并最终创建数据帧(Shikhardua的答案)
  • 结果(秒):

    1
    2
    3
    4
    Adding    1000 rows  5000 rows   10000 rows
    .append   0.69       3.37        6.77
    .loc      0.73       3.87        8.14
    dict      0.011      0.046       0.088

    还感谢@krassowski提供有用的评论-我更新了代码。

    所以我通过字典为自己添加了内容。

    代码:

    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
    29
    30
    31
    import pandas
    import numpy
    import time
    #%%
    del df1, df2, df3
    numOfRows = 1000
    startTime = time.perf_counter()
    df1 = pandas.DataFrame(numpy.random.randint(100, size=(5,5)), columns=['A', 'B', 'C', 'D', 'E'])
    for i in range( 1,numOfRows-4):
        df1 = df1.append( dict( (a,numpy.random.randint(100)) for a in ['A','B','C','D','E']), ignore_index=True)
    print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))
    print(df1.shape)

    startTime = time.perf_counter()
    df2 = pandas.DataFrame(numpy.random.randint(100, size=(5,5)), columns=['A', 'B', 'C', 'D', 'E'])
    for i in range( 1,numOfRows):
        df2.loc[i]  = numpy.random.randint(100, size=(1,5))[0]
    print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))
    print(df2.shape)

    startTime = time.perf_counter()
    row_list = []
    for i in range (0,5):
        row_list.append(dict( (a,numpy.random.randint(100)) for a in ['A','B','C','D','E']))
    for i in range( 1,numOfRows-4):
        dict1 = dict( (a,numpy.random.randint(100)) for a in ['A','B','C','D','E'])
        row_list.append(dict1)

    df3 = pandas.DataFrame(row_list, columns=['A','B','C','D','E'])
    print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))
    print(df3.shape)

    另外,我相信我的实现并不完美,也许还有一些优化。


    为了用Python的方式,这里添加我的答案:

    1
    2
    3
    4
    5
    6
    res = pd.DataFrame(columns=('lib', 'qty1', 'qty2'))
    res = res.append([{'qty1':10.0}], ignore_index=True)
    print(res.head())

       lib  qty1  qty2
    0  NaN  10.0   NaN


    这不是OP问题的答案,而是一个玩具例子来说明@shikhardua的答案,在上面我发现非常有用。

    虽然这个片段很小,但在实际数据中,我有1000行和许多列,我希望能够按不同的列分组,然后对多个标记列执行下面的统计。因此,一次建立一行数据帧的可靠方法是非常方便的。谢谢你@shikhardua!

    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
    import pandas as pd

    BaseData = pd.DataFrame({ 'Customer' : ['Acme','Mega','Acme','Acme','Mega','Acme'],
                              'Territory'  : ['West','East','South','West','East','South'],
                              'Product'  : ['Econ','Luxe','Econ','Std','Std','Econ']})
    BaseData

    columns = ['Customer','Num Unique Products', 'List Unique Products']

    rows_list=[]
    for name, group in BaseData.groupby('Customer'):
        RecordtoAdd={} #initialise an empty dict
        RecordtoAdd.update({'Customer' : name}) #
        RecordtoAdd.update({'Num Unique Products' : len(pd.unique(group['Product']))})      
        RecordtoAdd.update({'List Unique Products' : pd.unique(group['Product'])})                  

        rows_list.append(RecordtoAdd)

    AnalysedData = pd.DataFrame(rows_list)

    print('Base Data :
    '
    ,BaseData,'

     Analysed Data :
    '
    ,AnalysedData)

    您还可以构建列表列表并将其转换为数据帧-

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import pandas as pd

    rows = []
    columns = ['i','double','square']

    for i in range(6):
        row = [i, i*2, i*i]
        rows.append(row)

    df = pd.DataFrame(rows, columns=columns)

    1
    2
    3
    4
    5
    6
    7
        i   double  square
    0   0   0   0
    1   1   2   1
    2   2   4   4
    3   3   6   9
    4   4   8   16
    5   5   10  25


    想出一个简单而好的方法:

    1
    2
    3
    4
    5
    6
    7
    8
    >>> df
         A  B  C
    one  1  2  3
    >>> df.loc["two"] = [4,5,6]
    >>> df
         A  B  C
    one  1  2  3
    two  4  5  6

    创建新记录(数据帧)并添加到旧的数据帧。传递值列表和相应的列名以创建新的记录(数据帧)

    1
    2
    3
    new_record = pd.DataFrame([[0,'abcd',0,1,123]],columns=['a','b','c','d','e'])

    old_data_frame = pd.concat([old_data_frame,new_record])

    以下是在熊猫数据框中添加/附加行的方法

    1
    2
    3
    4
    5
    6
    def add_row(df, row):
        df.loc[-1] = row
        df.index = df.index + 1  
        return df.sort_index()

    add_row(df, [1,2,3])

    它可用于在空的或填充的熊猫数据框中插入/附加行。


    另一种方法(可能不是很有效):

    1
    2
    3
    4
    5
    6
    # add a row
    def add_row(df, row):
        colnames = list(df.columns)
        ncol = len(colnames)
        assert ncol == len(row),"Length of row must be the same as width of DataFrame: %s" % row
        return df.append(pd.DataFrame([row], columns=colnames))

    您还可以像这样增强数据帧类:

    1
    2
    3
    4
    import pandas as pd
    def add_row(self, row):
        self.loc[len(self.index)] = row
    pd.DataFrame.add_row = add_row

    简单点。将列表作为输入,在数据框中作为行附加:

    1
    2
    3
    4
    5
    import pandas as pd  
    res = pd.DataFrame(columns=('lib', 'qty1', 'qty2'))  
    for i in range(5):  
        res_list = list(map(int, input().split()))  
        res = res.append(pd.Series(res_list,index=['lib','qty1','qty2']), ignore_index=True)


    1
    2
    3
    4
    5
    6
    7
    import pandas as pd
    t1=pd.DataFrame()
    for i in range(len(the number of rows)):
        #add rows as columns
        t1[i]=list(rows)
    t1=t1.transpose()
    t1.columns=list(columns)

    这将负责向空数据帧添加项。问题是,对于第一个索引,df.index.max()==nan:

    1
    2
    3
    df = pd.DataFrame(columns=['timeMS', 'accelX', 'accelY', 'accelZ', 'gyroX', 'gyroY', 'gyroZ'])

    df.loc[0 if math.isnan(df.index.max()) else df.index.max() + 1] = [x for x in range(7)]