如何从pandas数据帧的不同列中选择多个值

时间:2018-03-21 18:45:00

标签: python pandas matplotlib

我正在尝试选择破坏记录高值或低值的值。我正在将每天具有高值和低值的DataFrame作为两个单独的列进行比较。最终目标是将新记录值的(日期,值)的散点图与旧记录值的折线图相对应(使用matplotlib。)

这是一个示例数据集。

set @T1 = @T2

所以它看起来像这样

new_data = {'Date': ['1/1/2015', '1/2/2015', '1/3/2015', '1/4/2015', '1/5/2015'],
        'new_low': [10, 25, 24, 21, 15],
        'new_high': [35, 37, 38, 55, 47]}


record_data = {'Day': ['1/1', '1/2', '1/3', '1/4', '1/5'],
           'record_low': [12, 28, 21, 25, 15],
           'record_high': [30, 40, 36, 57, 46]}

df_new = pd.DataFrame(new_data)
df_new.set_index('Date', inplace=True)

df_record = pd.DataFrame(record_data)
df_record.set_index('Day', inplace=True)

我希望结果能够沿着这条线看。

           new_low   new_high (new_data)
Date            
1/1/2015     10         35
1/2/2015     25         37
1/3/2015     24         38
1/4/2015     21         55
1/5/2015     15         47


       record_low   record_high (record_data)
Date            
1/1       12           30
1/2       28           40
1/3       21           36
1/4       25           57
1/5       15           46

由于我需要使用matplotlib的结果来制作散点图,我需要输入一个x值和y值列表。我的示例结果是我制作的数据帧,但它不需要。我可以使用两个单独的数组甚至是一个元组列表,我可以将 Date Record Value 0 1/1/2015 10 1 1/2/2015 25 2 1/4/2015 21 3 1/1/2015 35 4 1/3/2015 38 5 1/5/2015 47 放入x和y的列表中。

我觉得应该有一些简单/优雅的方式来做这个映射,但我没有足够的经验来找到它,我无法在其他地方找到答案。

我也有一些问题,如何输入记录数据只有一个月和一天作为日期戳,所以我只是将它们设置为同一年。它适用于我的可视化,但我宁愿不对数据这样做。

2 个答案:

答案 0 :(得分:1)

编辑以发表评论

这是一个解决方案,假设从文件读入数据并避免合并两个dfs来比较它们(请注意reindex步骤)。

# # skip the header and ensure the same naming of the columns
# # df_record has Date in format mon/day
df_record = pd.read_csv('record_data.tsv', sep='\t', 
                    skiprows=1, names=['Date','X', 'Y'], index_col = 'Date')

# #df_new has Date in format 'month/day/year'
df_new = pd.read_csv('new_data.tsv', sep='\t', skiprows=1, names=['Date','X', 'Y'])
df_new = df_new.set_index(df_new['Date'].apply(lambda x: "/".join(x.split('/')[:-1]))).drop('Date', axis = 1)

df_new = df_new.reindex(df_record.index)

# compare the columns
tdfX = (df_new['X'] < df_record['X'])
tdfY = (df_new['Y'] > df_record['Y'])

# get the data that is a new record
df_plot = pd.concat([df_new.loc[tdfY[tdfY].index, 'Y'], df_new.loc[tdfX[tdfX].index, 'X']]).to_frame('Record').reset_index()

答案 1 :(得分:0)

可能有更好的答案,但您可以将两个DataFrame合并在一起,然后通过比较列确定df_new值是否为记录。

我不会将日期设置为索引,只需将它们保留为列。它使它更好一点。如果它们是您的指数,那么首先执行此操作:

import pandas as pd
df_new['Date'] = df_new.index
df_record['Day'] = df_record.index

然后:

df_new['day'] = pd.to_datetime(df_new.Date).dt.day
df_new['month'] = pd.to_datetime(df_new.Date).dt.month

df_record['day'] = pd.to_datetime(df_record.Day, format='%M/%d').dt.day
df_record['month'] = pd.to_datetime(df_record.Day, format='%M/%d').dt.month

合并DataFrames并删除我们不再需要的列:

df = df_new.merge(df_record, on=['month', 'day']).drop(columns=['month', 'day', 'Day'])

然后检查值是否为记录。如果是这样,请创建一个包含记录值的新DataFrame:

record_low = df.X_x < df.X_y
record_high = df.Y_x > df.Y_y
pd.DataFrame({'Date': df[record_low]['Date'].tolist() + df[record_high]['Date'].tolist(), 
 'Record Value': df[record_low]['X_x'].tolist() + df[record_high]['Y_x'].tolist()})

    Date    Record Value
0   1/1/2015    10
1   1/2/2015    25
2   1/4/2015    21
3   1/1/2015    35
4   1/3/2015    38
5   1/5/2015    47