根据列的子集合并和更新数据帧

时间:2017-09-15 13:17:43

标签: python pandas dataframe

我想知道是否有最快的代码来替换两个for循环,假设df大小非常大。在我的实际情况中,每个数据帧是200行和25列。

data_df1 = np.array([['Name','Unit','Attribute','Date'],['a','A',1,2014],['b','B',2,2015],['c','C',3,2016],\
                 ['d','D',4,2017],['e','E',5,2018]])
data_df2 = np.array([['Name','Unit','Date'],['a','F',2019],['b','G',2020],['e','H',2021],\
                 ['f','I',2022]])
df1 = pd.DataFrame(data=data_df1)
print('df1:')
print(df1)
df2 = pd.DataFrame(data=data_df2)
print('df2:')
print(df2)
row_df1 = [1,2,5]
col_df1 = [1,3]
row_df2 = [1,2,3]
col_df2 = [1,2]
for i in range(0,len(row_df1)):
    for j in range(0, len(col_df1)):
        df1.set_value(row_df1[i],col_df1[j], df2.loc[row_df2[i],col_df2[j]])
print('df1 after operation:')
print(df1)

预期产出:

df1:
      0     1          2     3
0  Name  Unit  Attribute  Date
1     a     A          1  2014
2     b     B          2  2015
3     c     C          3  2016
4     d     D          4  2017
5     e     E          5  2018
df2:
      0     1     2
0  Name  Unit  Date
1     a     F  2019
2     b     G  2020
3     e     H  2021
4     f     I  2022
df1 after operation:
      0     1          2     3
0  Name  Unit  Attribute  Date
1     a     F          1  2019
2     b     G          2  2020
3     c     C          3  2016
4     d     D          4  2017
5     e     H          5  2021

我试过了:

df1.loc[[1,2,5],[1,3]] = df2.loc[[1,2,3],[1,2]]
print('df1:')
print(df1)
print('df2:')
print(df2)

但结果如下。有意想不到的南。

df1:
      0     1          2     3
0  Name  Unit  Attribute  Date
1     a     F          1   NaN
2     b     G          2   NaN
3     c     C          3  2016
4     d     D          4  2017
5     e   NaN          5   NaN
df2:
      0     1     2
0  Name  Unit  Date
1     a     F  2019
2     b     G  2020
3     e     H  2021
4     f     I  2022

提前感谢任何有帮助的人。

3 个答案:

答案 0 :(得分:2)

一些清洁:

React.Component

使用def clean_df(df): df.columns = df.iloc[0] df.columns.name = None df = df.iloc[1:].reset_index() return df df1 = clean_df(df1) df1 index Name Unit Attribute Date 0 1 a A 1 2014 1 2 b B 2 2015 2 3 c C 3 2016 3 4 d D 4 2017 4 5 e E 5 2018 df2 = clean_df(df2) df2 index Name Unit Date 0 1 a F 2019 1 2 b G 2020 2 3 e H 2021 3 4 f I 2022 ,指定merge,以便不考虑其他列。

on=Name

答案 1 :(得分:1)

另一种基于转置数据帧和ffill的合并和删除重复的方法,即

new_df = df1.merge(df2,on=[0],how='outer').T.set_index(0).sort_index()
        .ffill().reset_index().drop_duplicates(0,keep='last').T.dropna()
           0     2     3     5
0  Attribute  Date  Name  Unit
1          1  2019     a     F
2          2  2020     b     G
3          3  2016     c     C
4          4  2017     d     D
5          5  2021     e     H

解释

df1.merge(df2,on=[0],how='outer').T.set_index(0).sort_index()

转置数据帧将给出数据帧,以便我们可以应用ffill来填充nan值

            1     2     3     4     5     6
0                                            
Attribute     1     2     3     4     5   NaN
Date       2014  2015  2016  2017  2018   NaN
Date       2019  2020   NaN   NaN  2021  2022
Name          a     b     c     d     e     f
Unit          A     B     C     D     E   NaN
Unit          F     G   NaN   NaN     H     I
.ffill().reset_index().drop_duplicates(0,keep='last')

这将使用先前的行数据填充nan值,并使用子集0的重复数据删除reset_index,并保留最后一行将保留完全填充的行。

         0     1     2     3     4     5     6
0  Attribute     1     2     3     4     5   NaN
2       Date  2019  2020  2016  2017  2021  2022
3       Name     a     b     c     d     e     f
5       Unit     F     G     C     D     H     I
.T.dropna()

这将旋转数据帧,删除具有nan值的行,从而产生所需的输出。

答案 2 :(得分:0)

我还发现下面的代码做了我想要的,并且比两个for循环要快得多。

df1.loc[[1,2,5],[1,3]] = df2.loc[[1,2,3],[1,2]].values