使用 pandas (Python) 重塑 DataFrame
Reshaping DataFrame with pandas (Python)
首先我的英语不会很完美,很抱歉。
所以我在 python 上与 pandas 合作。我通过多种方式收集按时间戳索引的数据。
这意味着我可以有一个索引有 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 个索引。
不知道这样理解对不对。另一种方法是说我想要这个:每个时间戳的值数=特征数而不是=索引数。
非常感谢你的帮助,有没有关于这个问题的主题我不知道,请发给我一个link.
此解决方案假定您需要添加的数据是一个系列。
原始 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
替代答案(可能更简单,可能不那么pythonic)。我认为您通常需要考虑将宽数据转换为长数据并再次转换回来(旋转和转置可能是查找此内容的好方法),但我也认为您的问题中可能存在一些问题。您没有在后续数组的声明中提及新的列 1 和新的列 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
我认为您第一次创建第二个数据框的方式可能会出现一个问题。
实际上,根据其内容扩展特征的数量是使这种重新格式化在这里有点烦人的原因(正如您自己看到的那样,当编写两个新的列名时是出于赤裸裸的假设,即这反映了在每个时间戳观察到的特征的数量).
这是另一个解决方案,它试图在采取的步骤中比 更明确一些。
# 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])
现在唯一重要的一步基本上是转置你的第二个DataFrame,而在这里你还需要引入两个新的列名。
我们将根据其内容 (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
首先我的英语不会很完美,很抱歉。
所以我在 python 上与 pandas 合作。我通过多种方式收集按时间戳索引的数据。
这意味着我可以有一个索引有 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 个索引。
不知道这样理解对不对。另一种方法是说我想要这个:每个时间戳的值数=特征数而不是=索引数。
非常感谢你的帮助,有没有关于这个问题的主题我不知道,请发给我一个link.
此解决方案假定您需要添加的数据是一个系列。
原始 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
替代答案(可能更简单,可能不那么pythonic)。我认为您通常需要考虑将宽数据转换为长数据并再次转换回来(旋转和转置可能是查找此内容的好方法),但我也认为您的问题中可能存在一些问题。您没有在后续数组的声明中提及新的列 1 和新的列 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
我认为您第一次创建第二个数据框的方式可能会出现一个问题。 实际上,根据其内容扩展特征的数量是使这种重新格式化在这里有点烦人的原因(正如您自己看到的那样,当编写两个新的列名时是出于赤裸裸的假设,即这反映了在每个时间戳观察到的特征的数量).
这是另一个解决方案,它试图在采取的步骤中比
# 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])
现在唯一重要的一步基本上是转置你的第二个DataFrame,而在这里你还需要引入两个新的列名。 我们将根据其内容 (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