与熊猫一起重塑数据帧



所以我正在python上使用熊猫。我通过多种方式收集按时间戳索引的数据。

这意味着我可以有一个索引,其中包含 2 个可用功能(其他索引具有 NaN 值,这是正常的)或所有功能,这取决于。

所以我的问题是当我为相同的索引添加一些具有多个值的数据时,请参阅下面的示例:

想象一下,这是我们添加新数据的集合:

Index col1 col2
1   a    A
2   b    B
3   c    C

我们将添加这些数据:

Index new col 
1      z    
1      y    

那么结果是这样的:

Index col1 col2 new col
1   a    A    NaN
1   NaN  NaN  z
1   NaN  NaN  y
2   b    B    NaN
3   c    C    NaN

所以取而代之的是,我希望结果是:

Index col1 col2 new col1 new col2
1   a    A    z        y
2   b    B    NaN      NaN
3   c    C    NaN      NaN

我希望不是在 1 个功能中有多个索引,而是有多个功能有 1 个索引。

我不知道这是否可以理解。另一种方法是说我想要这个:每个时间戳的值数=特征数而不是=索引数。

此解决方案假定您需要添加的数据是一个序列。

原文 df:

df = pd.DataFrame(np.random.randint(0,3,size=(3,3)),columns = list('ABC'),index = [1,2,3])

要添加的数据(系列):

s = pd.Series(['x','y'],index = [1,1])

溶液:

df.join(s.to_frame()
.assign(cc = lambda x: x.groupby(level=0)
.cumcount().add(1))
.set_index('cc',append=True)[0]
.unstack()
.rename('New Col{}'.format,axis=1))

输出:

A  B  C New Col1 New Col2
1  1  2  2        x        y
2  0  1  2      NaN      NaN
3  2  2  0      NaN      NaN

替代答案(也许更简单,可能不那么python化)。我认为您需要考虑将宽数据转换为长数据,然后再将其转换为长数据(枢轴和转置可能是查找此的好东西),但我也认为您的问题中可能存在一些问题。在后续数组的声明中,您没有提到新的 col 1 和新的 col 2。

以下是我对您的数据框的声明:

d = {'index': [1, 2, 3],'col1': ['a', 'b', 'c'], 'col2': ['A', 'B', 'C']}
df = pd.DataFrame(data=d)
e1 = {'index': [1], 'new col1': ['z']}
dfe1 = pd.DataFrame(data=e1)
e2 = {'index': [1], 'new col2': ['y']}
dfe2 = pd.DataFrame(data=e2)

它们看起来像这样:

index   new col1
1       z

而这个:

index   new col2
1       y

请注意,我将新列声明为数据框的一部分。一旦它们被这样声明,就只需合并即可:

dfr = pd.merge(df, dfe, on='index', how="outer")
dfr1 = pd.merge(df, dfe1, on='index', how="outer")
dfr2 = pd.merge(dfr1, dfe2, on='index', how="outer")

输出如下所示:

index   col1    col2    new col1    new col2
1       a       A       z           y
2       b       B       NaN         NaN
3       c       C       NaN         NaN

我认为在第一次创建第二个数据框的方式中可能会出现一个问题。 实际上,根据其内容扩展功能的数量使这种重新格式化在这里有点烦人(正如您自己看到的那样,当编写两个新列名称时,这反映了在每个时间戳上观察到的特征数量)。

这是另一个解决方案,这试图在所采取的步骤中比 rhug123 的答案更明确一些。

# Initial dataFrames
a = pd.DataFrame({'col1':['a', 'b', 'c'], 'col2':['A', 'B', 'C']}, index=range(1, 4))
b = pd.DataFrame({'new col':['z', 'y']}, index=[1, 1])

现在唯一重要的步骤基本上是转置第二个数据帧,而在这里您还需要引入两个新的列名。 我们将根据其内容(y,z,...)对第二个数据帧进行分组:

c = b.groupby(b.index)['new col'].apply(list) # this has also one index per timestamp, but all features are grouped in a list
# New column names:
cols = ['New col%d'%(k+1) for in range(b.value_counts().sum())]
# Expanding dataframe "c" for each new column
d = pd.DataFrame(c.to_list(), index=b.index.unique(), columns=cols)
# Merge
a.join(d, how='outer')

输出:

col1 col2 New col1 New col2
1    a    A        z        y
2    b    B      NaN      NaN
3    c    C      NaN      NaN

最后,我的答案和 rhug123 的答案都遇到了一个问题是,就目前而言,它不会正确处理不同时间戳的另一个功能。不确定OP在这里期望什么。 例如,如果b是:

new col
1       z
1       y
2       x

合并的输出将是:

col1 col2 New col1 New col2
1    a    A        z        y
2    b    B        x     None
3    c    C      NaN      NaN

最新更新