Python 基于不同列中的值复制行
我有一个事务的数据框架。每行代表两个项目的事务(将其视为两个事件通知单或其他事务)。我想根据售出的数量复制每一行 下面是示例代码:Python 基于不同列中的值复制行,python,pandas,Python,Pandas,我有一个事务的数据框架。每行代表两个项目的事务(将其视为两个事件通知单或其他事务)。我想根据售出的数量复制每一行 下面是示例代码: # dictionary of transactions d = { '1': ['20', 'NYC', '2'], '2': ['30', 'NYC', '2'], '3': ['5', 'NYC', '2'], '4': ['300', 'LA', '2'], '5': ['30', 'LA', '2']
# dictionary of transactions
d = {
'1': ['20', 'NYC', '2'],
'2': ['30', 'NYC', '2'],
'3': ['5', 'NYC', '2'],
'4': ['300', 'LA', '2'],
'5': ['30', 'LA', '2'],
'6': ['100', 'LA', '2']
}
columns=['Price', 'City', 'Quantity']
# create dataframe and rename columns
df = pd.DataFrame.from_dict(
data=d, orient='index'
)
df.columns = columns
这将生成如下所示的数据帧
Price City Quantity
20 NYC 2
30 NYC 2
5 NYC 2
300 LA 2
30 LA 2
100 LA 2
因此,在上述情况下,每一行将转换为两个重复的行。如果“数量”列为3,则该行将转换为三个重复行。首先,我使用整数而不是文本重新创建数据。我还改变了数量,以便更容易理解问题
d = {1: [20, 'NYC', 1], 2: [30, 'NYC', 2], 3: [5, 'SF', 3],
4: [300, 'LA', 1], 5: [30, 'LA', 2], 6: [100, 'SF', 3]}
columns=['Price', 'City', 'Quantity']
# create dataframe and rename columns
df = pd.DataFrame.from_dict(data=d, orient='index').sort_index()
df.columns = columns
>>> df
Price City Quantity
1 20 NYC 1
2 30 NYC 2
3 5 SF 3
4 300 LA 1
5 30 LA 2
6 100 SF 3
我使用嵌套的列表理解结构创建了一个新的数据框架
df_new = pd.DataFrame([df.ix[idx]
for idx in df.index
for _ in range(df.ix[idx]['Quantity'])]).reset_index(drop=True)
>>> df_new
Price City Quantity
0 20 NYC 1
1 30 NYC 2
2 30 NYC 2
3 5 SF 3
4 5 SF 3
5 5 SF 3
6 300 LA 1
7 30 LA 2
8 30 LA 2
9 100 SF 3
10 100 SF 3
11 100 SF 3
这种方法怎么样。我稍微改变了一下你的数据,要求出售4张票 我们使用大小合适的helper np.ones()数组,然后代码的关键行是:
a[np.arange(a.shape[1])[:]>a[:,0,np.newaxis]=0
这里向我展示了这项技术:
然后,只需调用.stack()
,并完成一些基本过滤
d = {'1': ['20', 'NYC', '2'], '2': ['30', 'NYC', '2'], '3': ['5', 'NYC', '2'], \
'4': ['300', 'LA', '2'], '5': ['30', 'LA', '4'], '6': ['100', 'LA', '2']}
columns=['Price', 'City', 'Quantity']
df = pd.DataFrame.from_dict(data=d, orient='index')
df.columns = columns
df['Quantity'] = df['Quantity'].astype(int)
# make a ones array
my_ones = np.ones(shape=(len(df),df['Quantity'].max()))
# turn my_ones into a dataframe same index as df so we can join it to the right hand side. Plenty of other ways to achieve the same outcome.
df_my_ones = pd.DataFrame(data =my_ones,index = df.index)
df = df.join(df_my_ones)
这看起来像:
Price City Quantity 0 1 2 3
1 20 NYC 2 1 1 1 1
3 5 NYC 2 1 1 1 1
2 30 NYC 2 1 1 1 1
5 30 LA 4 1 1 1 1
4 300 LA 2 1 1 1 1
现在将数量列和数量列放入numpy数组中
a = df.iloc[:,2:].values
这是聪明的一点
a[np.arange(a.shape[1])[:] > a[:,0,np.newaxis]] = 0
并重新分配回df
df.iloc[:,2:] = a
现在df如下所示,注意我们是如何在数量上设置为零的:
Price City Quantity 0 1 2 3
1 20 NYC 2 1 1 0 0
3 5 NYC 2 1 1 0 0
2 30 NYC 2 1 1 0 0
5 30 LA 4 1 1 1 1
4 300 LA 2 1 1 0 0
df.set_index(['Price','City','Quantity'],inplace=True)
df = df.stack().to_frame()
df.columns = ['sale_flag']
df.reset_index(inplace=True)
print df[['Price','City', 'Quantity']][df['sale_flag'] !=0]
print df
产生:
Price City Quantity
0 20 NYC 2
1 20 NYC 2
4 5 NYC 2
5 5 NYC 2
8 30 NYC 2
9 30 NYC 2
12 30 LA 4
13 30 LA 4
14 30 LA 4
15 30 LA 4
16 300 LA 2
17 300 LA 2
使用
重复回答
df.loc[df.index.repeat(df.Quantity)]
Out[448]:
Price City Quantity
1 20 NYC 2
1 20 NYC 2
2 30 NYC 2
2 30 NYC 2
3 5 NYC 2
3 5 NYC 2
4 300 LA 2
4 300 LA 2
5 30 LA 2
5 30 LA 2
6 100 LA 2
6 100 LA 2
--您为此编写的代码在哪里?您得到了什么输出?您已经很好地描述了所需的输出,但这似乎没有堆栈溢出问题。请记住,代码修复是如此,而不是代码设计和编写。@Prune我不同意,这似乎符合特定编程问题的描述。OP可以使用一些指导来确定解决该问题的有效方法。有时一个人甚至不知道从哪里开始,一个丑陋的解决方案的尝试只会把问题弄得一团糟,浪费每个人的时间。我欣赏@Prune的建议,我大体上同意。我认为这是一个过滤掉纯粹懒惰问题的好方法。但这个问题确实让我感到困惑,我还不能为解决方案提供一个有意义的起点。谢谢。当我在实际数据上尝试时,我得到一个“TypeError:无法将序列转换为与第二个for循环相关”for u.in-range(df.ix[idx]['Quantity'])。请尝试以下操作:
for u.in-range(int(df.ix[idx]['Quantity'])
您还可以将列显式转换为整数:df Quantity']=dfQuantity.astype(int)
好的,我让它开始工作了。在我的数据集中,索引是一个日期时间序列,其中缺少一些日期(不确定是否相关)。当我像上面的例子那样将索引设置为正则连续整数时,它就起作用了。作为参考,当我运行df.Quantity.unique()时,我得到了“array([2,4,3,1,6,5,7,8,10,9,14,12],dtype=int64)”。非常感谢你的帮助。在这种情况下,您可能应该从df.reset\u index(inplace=True)
开始。顺便说一句,您帮我回答了最后一个问题。我真的很感激。非常有创意的解决方案!我得更仔细地检查一下。检查下面的其他响应,以了解不同的方法。非常感谢你的帮助。非常感谢。无意冒犯其他贡献者,但我认为这应该是公认的答案:)但它至少可以使用更多的信息。