【问题标题】:How can I copy DataFrames with datetimes from Stack Overflow into Python?如何将带有日期时间的 DataFrame 从 Stack Overflow 复制到 Python 中?
【发布时间】:2020-10-25 21:00:49
【问题描述】:

我经常看到关于 SO 的 pandas 示例使用时间序列,时间戳中有空格

                     A
2020-01-01 09:20:00  0
2020-01-01 09:21:00  1
2020-01-01 09:22:00  2
2020-01-01 09:23:00  3
2020-01-01 09:24:00  4

或者这个时间不是索引的一部分:

                dates    values cat
0 2020-01-01 09:20:00  0.758513   a
1 2020-01-01 09:21:00  0.337325   b
2 2020-01-01 09:22:00  0.618372   b
3 2020-01-01 09:23:00  0.878714   b
4 2020-01-01 09:24:00  0.311069   b

有没有一种好方法可以将这些(或类似的)数据复制回 Python 中使用?我发现了像 thisthis 这样的帖子,它们是获取许多示例的救命稻草SO,但我通常找不到适用于此类数据的复制/粘贴方法(使用pd.read_clipboard()pd.read_table())。这通常会阻止我尝试回答1

上面的例子是这样创建的:

#one
import pandas as pd
import numpy

dr = pd.date_range('01-01-2020 9:20', '01-01-2020 9:24', freq='1T')
df1 = pd.DataFrame(index=dr, data=range(len(dr)), columns=['A'])

#two
df2 = pd.DataFrame({'dates':dr,
                    'values':np.random.rand(len(dr)),
                    'cat':np.random.choice(['a','b'],len(dr))})

1。为了记录在案,我认为海报应该有责任以更可复制的格式发布他们的数据,否则不会得到答复。对于时间序列信息,我总是尝试发布构造代码(使用pd.date_range() 或w/e),而不是粘贴DataFrame 的字符串表示。我想如果有需要为示例复制特定(不规则间隔)日期,则使用 df.to_dict() 之类的东西会更好。

【问题讨论】:

  • 通常我会选择pd.read_clipboard(sep=\s\s+)
  • @HenryYik 这很好,我不知道sep 会修复第一个示例。但是第二次还是失败了?

标签: python pandas time-series clipboard copy-paste


【解决方案1】:

我通常对 Pandas SO 问题所做的只是简单地引用日期和时间值(在复制粘贴之后)。如果行很多,我将使用文本编辑器进行查找/替换,通常在年份模式 (20XX) 和日模式 (-01) 之后添加引号。从那里,使用StringIO,指定parse_dates,并根据需要在read.csv(或read.table)中指定index_col参数

日期时间作为索引

from io import StringIO
import pandas as pd

txt = '''             A
"2020-01-01 09:20:00" 0
"2020-01-01 09:21:00" 1
"2020-01-01 09:22:00" 2
"2020-01-01 09:23:00" 3
"2020-01-01 09:24:00" 4'''

df = pd.read_csv(StringIO(txt), sep="\s+", parse_dates=True)

df.index    
# DatetimeIndex(['2020-01-01 09:20:00', '2020-01-01 09:21:00',
#                '2020-01-01 09:22:00', '2020-01-01 09:23:00',
#                '2020-01-01 09:24:00'],
#               dtype='datetime64[ns]', freq=None)

日期时间列

txt = '''         dates    value  cat
0 "2020-01-01 09:20:00"  0.758513   a
1 "2020-01-01 09:21:00"  0.337325   b
2 "2020-01-01 09:22:00"  0.618372   b
3 "2020-01-01 09:23:00"  0.878714   b
4 "2020-01-01 09:24:00"  0.311069   b'''

df = pd.read_csv(StringIO(txt), sep="\s+", index_col=[0], parse_dates=["dates"])

df.dtypes
# dates     datetime64[ns]
# values           float64
# cat               object
# dtype: object

【讨论】:

    【解决方案2】:

    我通常复制整个字符串然后解析它。它并不完美,您通常必须同时编辑字符串和数据框以使其可用。这是一个例子。此解决方案已在此 answer 中提供。我只添加了一些关于解析日期/时间的内容。

    import pandas as pd
    from io import StringIO
    from dateutil.parser import parse
    
    # I added two more column names `date` and `time`.
    # An advantage of having the string in your python code is that
    # you can edit it in your text editor/jupyter notebook quickly and directly.
    s = """date time A
    2020-01-01 09:20:00  0
    2020-01-01 09:21:00  1
    2020-01-01 09:22:00  2
    2020-01-01 09:23:00  3
    2020-01-01 09:24:00  4"""
    
    # Parse using whitespace separator. This will still not be perfect as we can
    # see below.
    df = pd.read_csv(StringIO(s), sep="\s+", index_col=False)
    df
    #          date      time  A
    # 0  2020-01-01  09:20:00  0
    # 1  2020-01-01  09:21:00  1
    # 2  2020-01-01  09:22:00  2
    # 3  2020-01-01  09:23:00  3
    # 4  2020-01-01  09:24:00  4
    
    # Combine date and time column together and drop the individual columns.
    df['datetime'] = df['date'] + " " + df['time']
    df = df.drop(['date', 'time'], axis=1)
    
    # Use a somewhat universal parser in dateutil.parser.parse to parse the
    # dates into proper dateime object.
    df['datetime'] = df['datetime'].apply(parse)
    df
    #    A            datetime
    # 0  0 2020-01-01 09:20:00
    # 1  1 2020-01-01 09:21:00
    # 2  2 2020-01-01 09:22:00
    # 3  3 2020-01-01 09:23:00
    # 4  4 2020-01-01 09:24:00
    
    df.index
    # RangeIndex(start=0, stop=5, step=1)
    
    df.dtypes
    # A                    int64
    # datetime    datetime64[ns]
    # dtype: object
    
    df.columns
    # Index(['A', 'datetime'], dtype='object')
    

    在 StackOverflow 上提供格式化和可解析数据帧的一种方法是输出 csv 格式的字符串。

    # Continued from above
    print(df.to_csv(index=False))
    # A,datetime
    # 0,2020-01-01 09:20:00
    # 1,2020-01-01 09:21:00
    # 2,2020-01-01 09:22:00
    # 3,2020-01-01 09:23:00
    # 4,2020-01-01 09:24:00
    
    # We can indeed parse nicely from the csv-formatted string 
    s_redux = df.to_csv(index=False)
    pd.read_csv(StringIO(s_redux))
    #    A             datetime
    # 0  0  2020-01-01 09:20:00
    # 1  1  2020-01-01 09:21:00
    # 2  2  2020-01-01 09:22:00
    # 3  3  2020-01-01 09:23:00
    # 4  4  2020-01-01 09:24:00
    

    这是解析第二个示例数据帧的一种尝试。和以前一样,我们确实需要对数据框进行一些“编辑”以使其可用。

    import pandas as pd
    from io import StringIO
    from dateutil.parser import parse
    
    s="""                dates    values cat
    0 2020-01-01 09:20:00  0.758513   a
    1 2020-01-01 09:21:00  0.337325   b
    2 2020-01-01 09:22:00  0.618372   b
    3 2020-01-01 09:23:00  0.878714   b
    4 2020-01-01 09:24:00  0.311069   b"""
    
    df = pd.read_csv(StringIO(s), sep="\s+").reset_index()
    df
    #    level_0     level_1     dates    values cat
    # 0        0  2020-01-01  09:20:00  0.758513   a
    # 1        1  2020-01-01  09:21:00  0.337325   b
    # 2        2  2020-01-01  09:22:00  0.618372   b
    # 3        3  2020-01-01  09:23:00  0.878714   b
    # 4        4  2020-01-01  09:24:00  0.311069   b
    
    df['dates'] = df['level_1'] + " " + df['dates']
    df = df.drop(['level_0', 'level_1'], axis=1)
    df['dates'] = df['dates'].apply(parse)
    
    df
    #                 dates    values cat
    # 0 2020-01-01 09:20:00  0.758513   a
    # 1 2020-01-01 09:21:00  0.337325   b
    # 2 2020-01-01 09:22:00  0.618372   b
    # 3 2020-01-01 09:23:00  0.878714   b
    # 4 2020-01-01 09:24:00  0.311069   b
    
    df.dtypes
    # dates     datetime64[ns]
    # values           float64
    # cat               object
    # dtype: object
    

    【讨论】:

    • 考虑pandas.to_datetime,而不是apply + parse的循环版本。
    • 你说得对pd.to_datetime 应该更快,尤其是如果有重复的日期时间字符串。它还可以从多个列中解析日期时间,这应该非常有用。当性能不是问题时(例如 StackOverflow 数据帧),我碰巧喜欢dateutil.parser.parse,因为我一直在使用它来解析一般的日期时间。
    猜你喜欢
    • 2015-10-15
    • 2016-02-23
    • 1970-01-01
    • 2019-01-27
    • 2018-09-04
    • 1970-01-01
    • 1970-01-01
    • 2017-02-12
    • 2021-12-12
    相关资源
    最近更新 更多