串联新元数据并将其复制到所有行(熊猫)的最佳方法

时间:2019-02-22 12:38:15

标签: python pandas

我是熊猫新手。这应该很容易,但是我的方法似乎并不理想。

我有一个虚拟数据帧,其中包含几行和几列。接下来,我想包括一些具有单个值(一行)的元数据的新列。我想将其包含为新列,并希望将这些值复制到所有现有行中(这将使以后对数据进行某些操作更加容易)。

df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
                    'B': ['B0', 'B1', 'B2', 'B3'],
                    'C': ['C0', 'C1', 'C2', 'C3'],
                    'D': ['D0', 'D1', 'D2', 'D3']},
                   index=[0, 1, 2, 3])

df2 = pd.DataFrame({'LAT': ['LAT0'],
                    'LON': ['LON0'],
                    'TIME': ['T0']},
                   index=[0])

我想要一个具有4行7列(LAT,LON,TIME,A,B,C,D)的数据框。我希望每行重复输入LAT,LON和TIME中的值。

我的方法是:

df.insert(loc=0, column=['LAT'], value=df2['LAT'][0])

,并重复df2中的每个变量。这似乎很愚蠢,而不是正确的方法。此外,我可以:

df2.append(df1)

但这不会复制值。它充满了NaN。

执行这种简单的单行数据连接和复制的最佳方法是什么?

2 个答案:

答案 0 :(得分:4)

最简单的方法是将assign与字典一起使用**进行解包以添加新列,但是必须使用一个单词字符串列:

df1 = df1.assign(**df2.iloc[0])
print (df1)
    A   B   C   D   LAT   LON TIME
0  A0  B0  C0  D0  LAT0  LON0   T0
1  A1  B1  C1  D1  LAT0  LON0   T0
2  A2  B2  C2  D2  LAT0  LON0   T0
3  A3  B3  C3  D3  LAT0  LON0   T0

前置列的另一种解决方案是将reindexjoin结合使用:

df1 = df2.iloc[[0]].reindex(df1.index, method='ffill').join(df1)
print (df1)

    LAT   LON TIME   A   B   C   D
0  LAT0  LON0   T0  A0  B0  C0  D0
1  LAT0  LON0   T0  A1  B1  C1  D1
2  LAT0  LON0   T0  A2  B2  C2  D2
3  LAT0  LON0   T0  A3  B3  C3  D3

DataFrame建设者非常相似:

df3 = pd.DataFrame(df2.iloc[0].to_dict(), index=df1.index)
print (df3)
    LAT   LON TIME
0  LAT0  LON0   T0
1  LAT0  LON0   T0
2  LAT0  LON0   T0
3  LAT0  LON0   T0

df1 = df3.join(df1)
print (df1)
    LAT   LON TIME   A   B   C   D
0  LAT0  LON0   T0  A0  B0  C0  D0
1  LAT0  LON0   T0  A1  B1  C1  D1
2  LAT0  LON0   T0  A2  B2  C2  D2
3  LAT0  LON0   T0  A3  B3  C3  D3

另一个带有numpy.broadcast_to的numpy解决方案-仅当并非所有列都具有相同类型(如字符串)时,请小心,应该进行一些强制转换:

df3 = pd.DataFrame(np.broadcast_to(df2.values, (len(df1),len(df2.columns))),
                   columns=df2.columns, index=df1.index)
print (df3)
    LAT   LON TIME
0  LAT0  LON0   T0
1  LAT0  LON0   T0
2  LAT0  LON0   T0
3  LAT0  LON0   T0

df1 = df3.join(df1)
print (df1)

    LAT   LON TIME   A   B   C   D
0  LAT0  LON0   T0  A0  B0  C0  D0
1  LAT0  LON0   T0  A1  B1  C1  D1
2  LAT0  LON0   T0  A2  B2  C2  D2
3  LAT0  LON0   T0  A3  B3  C3  D3

性能

df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
                    'B': ['B0', 'B1', 'B2', 'B3'],
                    'C': ['C0', 'C1', 'C2', 'C3'],
                    'D': ['D0', 'D1', 'D2', 'D3']},
                   index=[0, 1, 2, 3])

#[400000 rows x 4 columns]
df1 = pd.concat([df1] * 100000, ignore_index=True)

df2 = pd.DataFrame({'LAT': ['LAT0'],
                    'LON': ['LON0'],
                    'TIME': ['T0']},
                    index=[0])



In [286]: %timeit df1.assign(**df2.iloc[0])
23 ms ± 642 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [287]: %timeit df2.iloc[[0]].reindex(df1.index, method='ffill').join(df1)
35.7 ms ± 3.78 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [288]: %timeit pd.DataFrame(df2.iloc[0].to_dict(), index=df1.index).join(df1)
54.7 ms ± 163 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [289]: %timeit pd.DataFrame(np.broadcast_to(df2.values, (len(df1),len(df2.columns))), columns=df2.columns, index=df1.index).join(df1)
27.8 ms ± 2.32 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

#bunji solution
In [290]: %timeit df1.join(df2, how='outer').fillna(method='ffill')
244 ms ± 19.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

答案 1 :(得分:1)

另一个选择是:

df = df1.join(df2, how='outer').fillna(method='ffill')
print(df)

    A   B   C   D   LAT   LON TIME
0  A0  B0  C0  D0  LAT0  LON0   T0
1  A1  B1  C1  D1  LAT0  LON0   T0
2  A2  B2  C2  D2  LAT0  LON0   T0
3  A3  B3  C3  D3  LAT0  LON0   T0

请注意,只有在how='outer'的行少于df1的情况下,df2才是真正必要的,因为join默认进行左连接。