计算清单形式存储的商品价格

时间:2019-11-17 10:27:39

标签: python pandas list dataframe metadata

我有一个看起来像这样的数据框:项目表

version: "3.2"

services:
  web:
    build: 
      context : .
      dockerfile: Dockerfile
    networks:
      - examplenetwork
    ports:
      - "5000:5000"
    depends_on:
      - db

  db:
    image: postgres
    networks:
      - examplenetwork
    volumes:
      - postgresql:/var/lib/postgresql
      - postgresql_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASS=admin 

networks:
  examplenetwork: 

volumes:
  postgresql:
  postgresql_data:

和另一个按日期存储每个项目价格的表。价格表

Date.    Item.     
10-sep.  X,Y,Z
11-sep.  Y,Z
12-sep.  Z
13-sep.  Z,X

我希望我的输出看起来像这样:

Item.   10sep.  11sep.   12sep.  13sep
X.       10.     5.        10.      15
Y.        7.     15.       13.       10
Z.        5.      10.       10.      10

第一行的总价格为22,因为9月10日X,Y和Z的价格分别为10,7和5。我可以知道如何获取此输出列。

3 个答案:

答案 0 :(得分:2)

我将使用此数据框解决您的问题

print(df1)
     Date          Item      
0  10-sep         X,Y,Z 
1  11-sep           Y,Z 
2  12-sep             Z 
3  13-sep           Z,X 

print(df2)
  Item     10sep    11sep     12sep    13sep
0    X        10        5        10       15
1    Y         7       15        13       10
2    Z         5       10        10       10

我们可以使用DataFrame.lookup 选择数据帧2的值,但首先我们必须准备值以进行搜索:

df3=df1.copy()
df3['Item']=df3['Item'].str.split(',')
df3=df3.explode('Item')
df3['Date']=df3['Date'].str.replace('-','')
print(df3)

    Date Item
0  10sep    X
0  10sep    Y
0  10sep    Z
1  11sep    Y
1  11sep    Z
2  12sep    Z
3  13sep    Z
3  13sep    X

mapper=df2.set_index('Item')


print(mapper)
      10sep  11sep  12sep  13sep
Item                            
X        10      5     10     15
Y         7     15     13     10
Z         5     10     10     10

df3['value']=mapper.lookup(df3['Item'],df3['Date'])
df1['Total Price']=df3.groupby(level=0).value.sum()
print(df1)
     Date          Item  Total Price
0  10-sep         X,Y,Z           22
1  11-sep           Y,Z           25
2  12-sep             Z           10
3  13-sep           Z,X           25

此数据帧的时间比较:

Valdi_Bo的方法:

%%timeit
ItemPrice = Prices.set_index('Item').stack().swaplevel().rename('Price')
def totalPrice(row):
    dat = row.Date
    items = row.Item.split(',')
    ind = pd.MultiIndex.from_arrays([[dat] * len(items), items])
    return ItemPrice.reindex(ind).sum()
Items['Total Price'] = Items.apply(totalPrice, axis=1)
13.5 ms ± 699 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

我的方法

%%timeit
df3=Items.copy()
df3['Item']=df3['Item'].str.split(',')
df3=df3.explode('Item')
mapper=Prices.set_index('Item')
df3['value']=mapper.lookup(df3['Item'],df3['Date'])
Items['Total Price']=df3.groupby(level=0).value.sum()
7.68 ms ± 178 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

@ anky_91方法

%%timeit
m=df2.set_index('Item').T
n=df1[['Date']].assign(**df1['Item'].str.get_dummies(',')).set_index('Date')
final=df1.set_index('Date').assign(Total_Price=m.mul(n).sum(1)).reset_index()
8.7 ms ± 199 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

答案 1 :(得分:2)

我假定两个DataFrame之间的最小顺序和协调,即:

  • 列名中没有尾随点。
  • 价格中列名称中的
  • 日期格式类似于项目日期列中的日期格式 (它们可以是 string 类型,但其中的两者都在日期后加减号。

因此商品价格数据框实际上如下:

     Date   Item
0  10-sep  X,Y,Z
1  11-sep    Y,Z
2  12-sep      Z
3  13-sep    Z,X

  Item  10-sep  11-sep  12-sep  13-sep
0    X      10       5      10      15
1    Y       7      15      13      10
2    Z       5      10      10      10 

第一步是将价格转换为系列

ItemPrice = Prices.set_index('Item').stack().swaplevel().rename('Price')

包含以下内容:

        Item
10-sep  X       10
11-sep  X        5
12-sep  X       10
13-sep  X       15
10-sep  Y        7
11-sep  Y       15
12-sep  Y       13
13-sep  Y       10
10-sep  Z        5
11-sep  Z       10
12-sep  Z       10
13-sep  Z       10
Name: Price, dtype: int64

然后定义一个函数来计算总价:

def totalPrice(row):
    dat = row.Date
    items = row.Item.split(',')
    ind = pd.MultiIndex.from_arrays([[dat] * len(items), items])
    return ItemPrice.reindex(ind).sum()

最后一步是将此功能应用于每一行并保存结果 作为新列:

Items['Total Price'] = Items.apply(totalPrice, axis=1)

结果是:

     Date   Item  Total Price
0  10-sep  X,Y,Z           22
1  11-sep    Y,Z           25
2  12-sep      Z           10
3  13-sep    Z,X           25

答案 2 :(得分:2)

以@Valdi_Bo的名义整理数据,您也可以尝试获取虚拟变量,并与转置的数据帧相乘并在axis = 1上求和,以获得所需的输出:

m=df2.set_index('Item').T
n=df1[['Date']].assign(**df1['Item'].str.get_dummies(',')).set_index('Date')
final=df1.set_index('Date').assign(Total_Price=m.mul(n).sum(1))

print(final)

         Item  Total_Price
Date                      
10-sep  X,Y,Z           22
11-sep    Y,Z           25
12-sep      Z           10
13-sep    Z,X           25