Pandas列数学运算 无错误无答案

9
我正在尝试对文件执行一些简单的数学运算。
下面的file_1.csv文件中的列是动态的,列数会随着时间的推移而增加。因此,我们不能有固定的last_column。
master_ids.csv:在任何预处理之前。
Ids,ref0 #the columns increase dynamically
1234,1000
8435,5243
2341,563
7352,345

master_count.csv : 在任何处理之前

Ids,Name,lat,lon,ref1
1234,London,40.4,10.1,500
8435,Paris,50.5,20.2,400
2341,NewYork,60.6,30.3,700
7352,Japan,70.7,80.8,500
1234,Prague,40.4,10.1,100
8435,Berlin,50.5,20.2,200
2341,Austria,60.6,30.3,500
7352,China,70.7,80.8,300

master_Ids.csv:经过一次预处理之后

Ids,ref,00:30:00
1234,1000,500
8435,5243,300
2341,563,400
7352,345,500

master_count.csv:期望的输出结果(追加/合并)

Ids,Name,lat,lon,ref1,00:30:00
1234,London,40.4,10.1,500,750
8435,Paris,50.5,20.2,400,550
2341,NewYork,60.6,30.3,700,900
7352,Japan,70.7,80.8,500,750
1234,Prague,40.4,10.1,100,350
8435,Berlin,50.5,20.2,200,350
2341,Austria,60.6,30.3,500,700
7352,China,70.7,80.8,300,750

例如:Ids:1234 出现了 2 次,因此在 当前时间(00:30:00) 时,ids: 1234 的值为 500,应该除以出现的 ids 次数,然后加上来自 ref1 的相应值,并创建一个具有当前时间的新列。

master_Ids.csv:经过另一种预处理之后

Ids,ref,00:30:00,00:45:00
1234,1000,500,100
8435,5243,300,200
2341,563,400,400
7352,345,500,600

master_count.csv:另一次执行(合并/追加)后的预期输出

Ids,Name,lat,lon,ref1,00:30:00,00:45:00
1234,London,40.4,10.1,500,750,550
8435,Paris,50.5,20.2,400,550,500
2341,NewYork,60.6,30.3,700,900,900
7352,Japan,70.7,80.8,500,750,800
1234,Prague,40.4,10.1,100,350,150
8435,Berlin,50.5,20.2,200,350,300
2341,Austria,60.6,30.3,500,700,700
7352,China,70.7,80.8,300,750,600

在这里,current time00:45:00,我们将current time value除以ids出现的count,然后通过创建一个带有new current time的新列,add到相应的ref1值中。
程序:由Jianxun Li编写。
import pandas as pd
import numpy as np

csv_file1 = '/Data_repository/master_ids.csv'
csv_file2 = '/Data_repository/master_count.csv'

df1 = pd.read_csv(csv_file1).set_index('Ids')

# need to sort index in file 2
df2 = pd.read_csv(csv_file2).set_index('Ids').sort_index()

# df1 and df2 has a duplicated column 00:00:00, use df1 without 1st column
temp = df2.join(df1.iloc[:, 1:])

# do the division by number of occurence of each Ids 
# and add column any time series
def my_func(group):
    num_obs = len(group)
    # process with column name after next timeseries (inclusive)
    group.iloc[:,4:] = (group.iloc[:,4:]/num_obs).add(group.iloc[:,3], axis=0)
    return group

result = temp.groupby(level='Ids').apply(my_func)

程序没有出现错误,也没有输出任何内容。请提供一些修复建议。

@BrenBarn 我无法进行重构,因为我需要旧的时间序列计数以备将来绘图之用。 - Sitz Blogz
我不确定你的意思。我所描述的更改不会导致任何信息丢失,只是不同的格式。 - BrenBarn
@BrenBarn 能否展示代码和输出格式,以便消除困惑? - Sitz Blogz
1
我在答案中添加了一个更新,请查看一下。另外,你能检查一下中国行的预期输出吗?我觉得除了那一行,其他行的结果都是符合预期的。 - JohnE
当我写了一个打印语句时,它没有错误也没有输出。然后我怀疑可能是我写错了语法。所以我请求 John 也包括 csv 文件的输出。结果我发现我的打印或追加语法是错误的。非常感谢你们两个的帮助。 - Sitz Blogz
显示剩余5条评论
3个回答

3

这个程序假设随着时间的推移,master_counts.csv和master_ids.csv都会进行更新,并且应该能够适应更新的时间。也就是说,如果在同一次更新上多次运行或者错过了一次更新,它应该能够产生正确的结果。

# this program updates (and replaces) the original master_counts.csv with data
# in master_ids.csv, so we only want the first 5 columns when we read it in
master_counts = pd.read_csv('master_counts.csv').iloc[:,:5]

# this file is assumed to be periodically updated with the addition of new columns
master_ids = pd.read_csv('master_ids.csv')

for i in range( 2, len(master_ids.columns) ):
    master_counts = master_counts.merge( master_ids.iloc[:,[0,i]], on='Ids' )
    count = master_counts.groupby('Ids')['ref1'].transform('count')
    master_counts.iloc[:,-1] = master_counts['ref1'] + master_counts.iloc[:,-1]/count

master_counts.to_csv('master_counts.csv',index=False)

%more master_counts.csv
Ids,Name,lat,lon,ref1,00:30:00,00:45:00
1234,London,40.4,10.1,500,750.0,550.0
1234,Prague,40.4,10.1,100,350.0,150.0
8435,Paris,50.5,20.2,400,550.0,500.0
8435,Berlin,50.5,20.2,200,350.0,300.0
2341,NewYork,60.6,30.3,700,900.0,900.0
2341,Austria,60.6,30.3,500,700.0,700.0
7352,Japan,70.7,80.8,500,750.0,800.0
7352,China,70.7,80.8,300,550.0,600.0

请问您能否提供更加清晰易懂的代码呢? - Sitz Blogz
请查看问题中的编辑部分描述。 - Sitz Blogz
第一个程序无法使用,因为 master_ids.csv 文件不会更改,只会不断追加。更新后的版本可以正常运行,没有错误,同时也没有输出。 - Sitz Blogz
我正在检查 master_count.csv,但是我没有看到任何更新。输出需要附加在 master_count.csv 中。 - Sitz Blogz
1
@SitzBlogz 好的,我明确地添加了CSV输出。这是最简单的部分,我假设你已经知道如何做了。 - JohnE
我应该知道如何使用纯Python和字典进行编程... 由于我对Pandas不熟悉,所以遇到了一些麻烦。如果您有空帮忙解决这个问题,那将是非常大的帮助。链接:http://stackoverflow.com/questions/31201986/date-time-series-wise-grouping-of-data-and-distribution/31369106#31369106 - Sitz Blogz

2

我的建议是重新格式化你的数据,使其像这样:

Ids,ref0,current_time,ref1
1234,1000,None,None
8435,5243,None,None
2341,563,None,None
7352,345,None,None

然后在您的“第一次预处理”之后,它会变成这样:
Ids,ref0,time,ref1
1234,1000,None,None
8435,5243,None,None
2341,563,None,None
7352,345,None,None
1234,1000,00:30:00,500
8435,5243,00:30:00,300
2341,563,00:30:00,400
7352,345,00:30:00,500

. . .等等。思路是您应该创建一个单独的列来保存时间信息,然后对于每个预处理,将新数据插入到新的中,并为这些行在时间列中赋值,表示它们来自哪个时间段。您可能希望在此表中保留具有“无”值的初始行;也许您只想从“00:30:00”值开始,并将“主ID”保存在单独的文件中。

我没有完全按照您计算新的ref1值的方式,但重点是这样做可能会极大地简化您的生活。通常,与添加无限数量的新列相比,添加一个单独的新列可以更加美观,其值将是您要用作开放式新列标题的值。


2
import pandas as pd
import numpy as np

csv_file1 = '/home/Jian/Downloads/stack_flow_bundle/Data_repository/master_lac_Test.csv'
csv_file2 = '/home/Jian/Downloads/stack_flow_bundle/Data_repository/lat_lon_master.csv'

df1 = pd.read_csv(csv_file1).set_index('Ids')

Out[53]: 
      00:00:00  00:30:00  00:45:00
Ids                               
1234      1000       500       100
8435      5243       300       200
2341       563       400       400
7352       345       500       600

# need to sort index in file 2
df2 = pd.read_csv(csv_file2).set_index('Ids').sort_index()

Out[81]: 
         Name   lat   lon  00:00:00
Ids                                
1234   London  40.4  10.1       500
1234   Prague  40.4  10.1       500
2341  NewYork  60.6  30.3       700
2341  Austria  60.6  30.3       700
7352    Japan  70.7  80.8       500
7352    China  70.7  80.8       500
8435    Paris  50.5  20.2       400
8435   Berlin  50.5  20.2       400

# df1 and df2 has a duplicated column 00:00:00, use df1 without 1st column
temp = df2.join(df1.iloc[:, 1:])



Out[55]: 
         Name   lat   lon  00:00:00  00:30:00  00:45:00
Ids                                                    
1234   London  40.4  10.1       500       500       100
1234   Prague  40.4  10.1       500       500       100
2341  NewYork  60.6  30.3       700       400       400
2341  Austria  60.6  30.3       700       400       400
7352    Japan  70.7  80.8       500       500       600
7352    China  70.7  80.8       500       500       600
8435    Paris  50.5  20.2       400       300       200
8435   Berlin  50.5  20.2       400       300       200

# do the division by number of occurence of each Ids 
# and add column 00:00:00
def my_func(group):
    num_obs = len(group)
    # process with column name after 00:30:00 (inclusive)
    group.iloc[:,4:] = (group.iloc[:,4:]/num_obs).add(group.iloc[:,3], axis=0)
    return group



result = temp.groupby(level='Ids').apply(my_func)

Out[104]: 
         Name   lat   lon  00:00:00  00:30:00  00:45:00
Ids                                                    
1234   London  40.4  10.1       500       750       550
1234   Prague  40.4  10.1       500       750       550
2341  NewYork  60.6  30.3       700       900       900
2341  Austria  60.6  30.3       700       900       900
7352    Japan  70.7  80.8       500       750       800
7352    China  70.7  80.8       500       750       800
8435    Paris  50.5  20.2       400       550       500
8435   Berlin  50.5  20.2       400       550       500

我看到有些混淆,请阅读我编辑后更清晰的问题。 - Sitz Blogz
1
@SitzBlogz 我已经修改了代码。请告诉我这是否是你想要的。 - Jianxun Li
答案看起来就像我需要的,但是“00:30:00 和 00:45:00”列是动态的。 File_1 可能有任何时间序列,请您更改那部分。 - Sitz Blogz
1
@SitzBlogz 我已经修改了my_func部分,使用了.iloc代替.loc - Jianxun Li
你能否也尝试帮助这个问题:http://stackoverflow.com/questions/31201986/date-time-series-wise-grouping-of-data-and-distribution - Sitz Blogz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接